protected bool DecodePrediction( DeltaBuffer deltaBuffer, ushort currentSequence, ushort resetSequence, int numCubes, ref int[] cubeIds, ref bool[] perfectPrediction, ref bool[] hasPredictionDelta, ref ushort[] baselineSequence, ref CubeState[] cubeState, ref CubeDelta[] predictionDelta ) { Profiler.BeginSample( "DecodePrediction" ); CubeState baselineCubeState = CubeState.defaults; bool result = true; #if !DISABLE_DELTA_ENCODING for ( int i = 0; i < numCubes; ++i ) { if ( perfectPrediction[i] || hasPredictionDelta[i] ) { if ( deltaBuffer.GetCubeState( baselineSequence[i], resetSequence, cubeIds[i], ref baselineCubeState ) ) { int baseline_sequence = baselineSequence[i]; int current_sequence = currentSequence; if ( current_sequence < baseline_sequence ) current_sequence += 65536; int baseline_position_x = baselineCubeState.position_x; int baseline_position_y = baselineCubeState.position_y; int baseline_position_z = baselineCubeState.position_z; int baseline_linear_velocity_x = baselineCubeState.linear_velocity_x; int baseline_linear_velocity_y = baselineCubeState.linear_velocity_y; int baseline_linear_velocity_z = baselineCubeState.linear_velocity_z; int baseline_angular_velocity_x = baselineCubeState.angular_velocity_x; int baseline_angular_velocity_y = baselineCubeState.angular_velocity_y; int baseline_angular_velocity_z = baselineCubeState.angular_velocity_z; if ( current_sequence < baseline_sequence ) current_sequence += 65536; int numFrames = current_sequence - baseline_sequence; int predicted_position_x; int predicted_position_y; int predicted_position_z; int predicted_linear_velocity_x; int predicted_linear_velocity_y; int predicted_linear_velocity_z; int predicted_angular_velocity_x; int predicted_angular_velocity_y; int predicted_angular_velocity_z; Prediction.PredictBallistic( numFrames, baseline_position_x, baseline_position_y, baseline_position_z, baseline_linear_velocity_x, baseline_linear_velocity_y, baseline_linear_velocity_z, baseline_angular_velocity_x, baseline_angular_velocity_y, baseline_angular_velocity_z, out predicted_position_x, out predicted_position_y, out predicted_position_z, out predicted_linear_velocity_x, out predicted_linear_velocity_y, out predicted_linear_velocity_z, out predicted_angular_velocity_x, out predicted_angular_velocity_y, out predicted_angular_velocity_z ); if ( perfectPrediction[i] ) { #if DEBUG_DELTA_COMPRESSION Assert.IsTrue( predicted_position_x == cubeDelta[i].absolute_position_x ); Assert.IsTrue( predicted_position_y == cubeDelta[i].absolute_position_y ); Assert.IsTrue( predicted_position_z == cubeDelta[i].absolute_position_z ); #endif // #if DEBUG_DELTA_COMPRESSION cubeState[i].position_x = predicted_position_x; cubeState[i].position_y = predicted_position_y; cubeState[i].position_z = predicted_position_z; cubeState[i].linear_velocity_x = predicted_linear_velocity_x; cubeState[i].linear_velocity_y = predicted_linear_velocity_y; cubeState[i].linear_velocity_z = predicted_linear_velocity_z; cubeState[i].angular_velocity_x = predicted_angular_velocity_x; cubeState[i].angular_velocity_y = predicted_angular_velocity_y; cubeState[i].angular_velocity_z = predicted_angular_velocity_z; } else { cubeState[i].position_x = predicted_position_x + predictionDelta[i].position_delta_x; cubeState[i].position_y = predicted_position_y + predictionDelta[i].position_delta_y; cubeState[i].position_z = predicted_position_z + predictionDelta[i].position_delta_z; #if DEBUG_DELTA_COMPRESSION Assert.IsTrue( cubeState[i].position_x == cubeDelta[i].absolute_position_x ); Assert.IsTrue( cubeState[i].position_y == cubeDelta[i].absolute_position_y ); Assert.IsTrue( cubeState[i].position_z == cubeDelta[i].absolute_position_z ); #endif // #if DEBUG_DELTA_COMPRESSION cubeState[i].linear_velocity_x = predicted_linear_velocity_x + predictionDelta[i].linear_velocity_delta_x; cubeState[i].linear_velocity_y = predicted_linear_velocity_y + predictionDelta[i].linear_velocity_delta_y; cubeState[i].linear_velocity_z = predicted_linear_velocity_z + predictionDelta[i].linear_velocity_delta_z; cubeState[i].angular_velocity_x = predicted_angular_velocity_x + predictionDelta[i].angular_velocity_delta_x; cubeState[i].angular_velocity_y = predicted_angular_velocity_y + predictionDelta[i].angular_velocity_delta_y; cubeState[i].angular_velocity_z = predicted_angular_velocity_z + predictionDelta[i].angular_velocity_delta_z; } } else { Debug.Log( "error: missing baseline for cube " + cubeIds[i] + " at sequence " + baselineSequence[i] + " (perfect prediction and prediction delta)" ); result = false; break; } } } #endif // #if !DISABLE_DELTA_COMPRESSION Profiler.EndSample(); return result; }
bool DecodePrediction(DeltaBuffer buffer, ushort currentId, ushort resetId, int cubeCount, ref int[] cubeIds, ref bool[] hasPerfectPrediction, ref bool[] hasPrediction, ref ushort[] baselineIds, ref CubeState[] states, ref CubeDelta[] predictions ) { Profiler.BeginSample("DecodePrediction"); var baseline = CubeState.defaults; var result = true; #if !DISABLE_DELTA_ENCODING for (int i = 0; i < cubeCount; ++i) { if (!hasPerfectPrediction[i] && !hasPrediction[i]) { continue; } if (!buffer.GetPacketCube(baselineIds[i], resetId, cubeIds[i], ref baseline)) { Debug.Log("error: missing baseline for cube " + cubeIds[i] + " at sequence " + baselineIds[i] + " (perfect prediction and prediction delta)"); result = false; break; } int id = currentId; if (id < baselineIds[i]) { id += 65536; } if (id < baselineIds[i]) { id += 65536; } int positionX; int positionY; int positionZ; int linearVelocityX; int linearVelocityY; int linearVelocityZ; int angularVelocityX; int angularVelocityY; int angularVelocityZ; Prediction.PredictBallistic(id - baselineIds[i], baseline.positionX, baseline.positionY, baseline.positionZ, baseline.linearVelocityX, baseline.linearVelocityY, baseline.linearVelocityZ, baseline.angularVelocityX, baseline.angularVelocityY, baseline.angularVelocityZ, out positionX, out positionY, out positionZ, out linearVelocityX, out linearVelocityY, out linearVelocityZ, out angularVelocityX, out angularVelocityY, out angularVelocityZ); if (hasPerfectPrediction[i]) { #if DEBUG_DELTA_COMPRESSION Assert.IsTrue(predicted_position_x == cubeDelta[i].absolute_position_x); Assert.IsTrue(predicted_position_y == cubeDelta[i].absolute_position_y); Assert.IsTrue(predicted_position_z == cubeDelta[i].absolute_position_z); #endif // #if DEBUG_DELTA_COMPRESSION states[i].positionY = positionY; states[i].positionZ = positionZ; states[i].linearVelocityX = linearVelocityX; states[i].linearVelocityY = linearVelocityY; states[i].linearVelocityZ = linearVelocityZ; states[i].angularVelocityX = angularVelocityX; states[i].angularVelocityY = angularVelocityY; states[i].angularVelocityZ = angularVelocityZ; continue; } states[i].positionX = positionX + predictions[i].positionX; states[i].positionY = positionY + predictions[i].positionY; states[i].positionZ = positionZ + predictions[i].positionZ; #if DEBUG_DELTA_COMPRESSION Assert.IsTrue(cubeState[i].position_x == cubeDelta[i].absolute_position_x); Assert.IsTrue(cubeState[i].position_y == cubeDelta[i].absolute_position_y); Assert.IsTrue(cubeState[i].position_z == cubeDelta[i].absolute_position_z); #endif // #if DEBUG_DELTA_COMPRESSION states[i].linearVelocityX = linearVelocityX + predictions[i].linearVelocityX; states[i].linearVelocityY = linearVelocityY + predictions[i].linearVelocityY; states[i].linearVelocityZ = linearVelocityZ + predictions[i].linearVelocityZ; states[i].angularVelocityX = angularVelocityX + predictions[i].angularVelocityX; states[i].angularVelocityY = angularVelocityY + predictions[i].angularVelocityY; states[i].angularVelocityZ = angularVelocityZ + predictions[i].angularVelocityZ; } #endif // #if !DISABLE_DELTA_COMPRESSION Profiler.EndSample(); return(result); }
protected void DeterminePrediction( Context context, Context.ConnectionData connectionData, ushort currentSequence, int numCubes, ref int[] cubeIds, ref bool[] notChanged, ref bool[] hasDelta, ref bool[] perfectPrediction, ref bool[] hasPredictionDelta, ref ushort[] baselineSequence, ref CubeState[] cubeState, ref CubeDelta[] predictionDeltas ) { Profiler.BeginSample( "DeterminePrediction" ); CubeState baselineCubeState = CubeState.defaults; for ( int i = 0; i < numCubes; ++i ) { perfectPrediction[i] = false; hasPredictionDelta[i] = false; #if !DISABLE_DELTA_ENCODING if ( notChanged[i] ) continue; if ( !hasDelta[i] ) continue; if ( !cubeState[i].active ) continue; if ( context.GetMostRecentAckedState( connectionData, cubeIds[i], ref baselineSequence[i], context.GetResetSequence(), ref baselineCubeState ) ) { if ( Network.Util.BaselineDifference( currentSequence, baselineSequence[i] ) <= Constants.MaxBaselineDifference ) { // baseline is too far behind. send the cube state absolute continue; } if ( !baselineCubeState.active ) { // no point predicting if the cube is at rest. continue; } int baseline_sequence = baselineSequence[i]; int current_sequence = currentSequence; if ( current_sequence < baseline_sequence ) current_sequence += 65536; int baseline_position_x = baselineCubeState.position_x; int baseline_position_y = baselineCubeState.position_y; int baseline_position_z = baselineCubeState.position_z; int baseline_linear_velocity_x = baselineCubeState.linear_velocity_x; int baseline_linear_velocity_y = baselineCubeState.linear_velocity_y; int baseline_linear_velocity_z = baselineCubeState.linear_velocity_z; int baseline_angular_velocity_x = baselineCubeState.angular_velocity_x; int baseline_angular_velocity_y = baselineCubeState.angular_velocity_y; int baseline_angular_velocity_z = baselineCubeState.angular_velocity_z; if ( current_sequence < baseline_sequence ) current_sequence += 65536; int numFrames = current_sequence - baseline_sequence; int predicted_position_x; int predicted_position_y; int predicted_position_z; int predicted_linear_velocity_x; int predicted_linear_velocity_y; int predicted_linear_velocity_z; int predicted_angular_velocity_x; int predicted_angular_velocity_y; int predicted_angular_velocity_z; Prediction.PredictBallistic( numFrames, baseline_position_x, baseline_position_y, baseline_position_z, baseline_linear_velocity_x, baseline_linear_velocity_y, baseline_linear_velocity_z, baseline_angular_velocity_x, baseline_angular_velocity_y, baseline_angular_velocity_z, out predicted_position_x, out predicted_position_y, out predicted_position_z, out predicted_linear_velocity_x, out predicted_linear_velocity_y, out predicted_linear_velocity_z, out predicted_angular_velocity_x, out predicted_angular_velocity_y, out predicted_angular_velocity_z ); int current_position_x = cubeState[i].position_x; int current_position_y = cubeState[i].position_y; int current_position_z = cubeState[i].position_z; int current_linear_velocity_x = cubeState[i].linear_velocity_x; int current_linear_velocity_y = cubeState[i].linear_velocity_y; int current_linear_velocity_z = cubeState[i].linear_velocity_z; int current_angular_velocity_x = cubeState[i].angular_velocity_x; int current_angular_velocity_y = cubeState[i].angular_velocity_y; int current_angular_velocity_z = cubeState[i].angular_velocity_z; int position_error_x = current_position_x - predicted_position_x; int position_error_y = current_position_y - predicted_position_y; int position_error_z = current_position_z - predicted_position_z; int linear_velocity_error_x = current_linear_velocity_x - predicted_linear_velocity_x; int linear_velocity_error_y = current_linear_velocity_y - predicted_linear_velocity_y; int linear_velocity_error_z = current_linear_velocity_z - predicted_linear_velocity_z; int angular_velocity_error_x = current_angular_velocity_x - predicted_angular_velocity_x; int angular_velocity_error_y = current_angular_velocity_y - predicted_angular_velocity_y; int angular_velocity_error_z = current_angular_velocity_z - predicted_angular_velocity_z; if ( position_error_x == 0 && position_error_y == 0 && position_error_z == 0 && linear_velocity_error_x == 0 && linear_velocity_error_y == 0 && linear_velocity_error_z == 0 && angular_velocity_error_x == 0 && angular_velocity_error_y == 0 && angular_velocity_error_z == 0 ) { perfectPrediction[i] = true; } else { int abs_position_error_x = Math.Abs( position_error_x ); int abs_position_error_y = Math.Abs( position_error_y ); int abs_position_error_z = Math.Abs( position_error_z ); int abs_linear_velocity_error_x = Math.Abs( linear_velocity_error_x ); int abs_linear_velocity_error_y = Math.Abs( linear_velocity_error_y ); int abs_linear_velocity_error_z = Math.Abs( linear_velocity_error_z ); int abs_angular_velocity_error_x = Math.Abs( angular_velocity_error_x ); int abs_angular_velocity_error_y = Math.Abs( angular_velocity_error_y ); int abs_angular_velocity_error_z = Math.Abs( angular_velocity_error_z ); int total_prediction_error = abs_position_error_x + abs_position_error_y + abs_position_error_z + linear_velocity_error_x + linear_velocity_error_y + linear_velocity_error_z + angular_velocity_error_x + angular_velocity_error_y + angular_velocity_error_z; int total_absolute_error = Math.Abs( cubeState[i].position_x - baselineCubeState.position_x ) + Math.Abs( cubeState[i].position_y - baselineCubeState.position_y ) + Math.Abs( cubeState[i].position_z - baselineCubeState.position_z ) + Math.Abs( cubeState[i].linear_velocity_x - baselineCubeState.linear_velocity_x ) + Math.Abs( cubeState[i].linear_velocity_y - baselineCubeState.linear_velocity_y ) + Math.Abs( cubeState[i].linear_velocity_z - baselineCubeState.linear_velocity_z ) + Math.Abs( cubeState[i].angular_velocity_x - baselineCubeState.angular_velocity_x ) + Math.Abs( cubeState[i].angular_velocity_y - baselineCubeState.angular_velocity_y ) + Math.Abs( cubeState[i].angular_velocity_z - baselineCubeState.angular_velocity_z ); if ( total_prediction_error < total_absolute_error ) { int max_position_error = abs_position_error_x; if ( abs_position_error_y > max_position_error ) max_position_error = abs_position_error_y; if ( abs_position_error_z > max_position_error ) max_position_error = abs_position_error_z; int max_linear_velocity_error = abs_linear_velocity_error_x; if ( abs_linear_velocity_error_y > max_linear_velocity_error ) max_linear_velocity_error = abs_linear_velocity_error_y; if ( abs_linear_velocity_error_z > max_linear_velocity_error ) max_linear_velocity_error = abs_linear_velocity_error_z; int max_angular_velocity_error = abs_angular_velocity_error_x; if ( abs_angular_velocity_error_y > max_angular_velocity_error ) max_angular_velocity_error = abs_angular_velocity_error_y; if ( abs_angular_velocity_error_z > max_angular_velocity_error ) max_angular_velocity_error = abs_angular_velocity_error_z; if ( max_position_error <= Constants.PositionDeltaMax && max_linear_velocity_error <= Constants.LinearVelocityDeltaMax && max_angular_velocity_error <= Constants.AngularVelocityDeltaMax ) { hasPredictionDelta[i] = true; predictionDelta[i].position_delta_x = position_error_x; predictionDelta[i].position_delta_y = position_error_y; predictionDelta[i].position_delta_z = position_error_z; predictionDelta[i].linear_velocity_delta_x = linear_velocity_error_x; predictionDelta[i].linear_velocity_delta_y = linear_velocity_error_y; predictionDelta[i].linear_velocity_delta_z = linear_velocity_error_z; predictionDelta[i].angular_velocity_delta_x = angular_velocity_error_x; predictionDelta[i].angular_velocity_delta_y = angular_velocity_error_y; predictionDelta[i].angular_velocity_delta_z = angular_velocity_error_z; } } } } } #endif // #if !DISABLE_DELTA_ENCODING Profiler.EndSample(); }
protected void DeterminePrediction(Context context, Context.NetworkData data, ushort currentId, int cubeCount, ref int[] cubeIds, ref bool[] notChanged, ref bool[] hasDelta, ref bool[] hasPerfectPrediction, ref bool[] hasPrediction, ref ushort[] baselineIds, ref CubeState[] cubes, ref CubeDelta[] predictions ) { BeginSample("DeterminePrediction"); var baseline = CubeState.defaults; for (int i = 0; i < cubeCount; ++i) { hasPerfectPrediction[i] = false; hasPrediction[i] = false; #if !DISABLE_DELTA_ENCODING if (notChanged[i] || !hasDelta[i] || !cubes[i].isActive || !context.GetAckedCube(data, cubeIds[i], ref baselineIds[i], context.resetId, ref baseline) || Util.BaselineDifference(currentId, baselineIds[i]) <= MaxBaselineDifference //baseline is too far behind. send the cube state absolute || !baseline.isActive //no point predicting if the cube is at rest. ) continue; int id = currentId; if (id < baselineIds[i]) id += 65536; if (id < baselineIds[i]) id += 65536; Prediction.PredictBallistic(id - baselineIds[i], baseline.positionX, baseline.positionY, baseline.positionZ, baseline.linearVelocityX, baseline.linearVelocityY, baseline.linearVelocityZ, baseline.angularVelocityX, baseline.angularVelocityY, baseline.angularVelocityZ, out int positionX, out int positionY, out int positionZ, out int linearVelocityX, out int linearVelocityY, out int linearVelocityZ, out int angularVelocityX, out int angularVelocityY, out int angularVelocityZ); int positionLagX = cubes[i].positionX - positionX; int positionLagY = cubes[i].positionY - positionY; int positionLagZ = cubes[i].positionZ - positionZ; int linearVelocityLagX = cubes[i].linearVelocityX - linearVelocityX; int linearVelocityLagY = cubes[i].linearVelocityY - linearVelocityY; int linearVelocityLagZ = cubes[i].linearVelocityZ - linearVelocityZ; int angularVelocityLagX = cubes[i].angularVelocityX - angularVelocityX; int angularVelocityLagY = cubes[i].angularVelocityY - angularVelocityY; int angularVelocityLagZ = cubes[i].angularVelocityZ - angularVelocityZ; if (positionLagX == 0 && positionLagY == 0 && positionLagZ == 0 && linearVelocityLagX == 0 && linearVelocityLagY == 0 && linearVelocityLagZ == 0 && angularVelocityLagX == 0 && angularVelocityLagY == 0 && angularVelocityLagZ == 0 ) { hasPerfectPrediction[i] = true; continue; } int absPositionX = Math.Abs(positionLagX); int absPositionY = Math.Abs(positionLagY); int absPositionZ = Math.Abs(positionLagZ); int absLinearVelocityX = Math.Abs(linearVelocityLagX); int absLinearVelocityY = Math.Abs(linearVelocityLagY); int absLinearVelocityZ = Math.Abs(linearVelocityLagZ); int absAngularVelocityX = Math.Abs(angularVelocityLagX); int absAngularVelocityY = Math.Abs(angularVelocityLagY); int absAngularVelocityZ = Math.Abs(angularVelocityLagZ); int predictedLag = absPositionX + absPositionY + absPositionZ + linearVelocityLagX + linearVelocityLagY + linearVelocityLagZ + angularVelocityLagX + angularVelocityLagY + angularVelocityLagZ; int absoluteLag = Math.Abs(cubes[i].positionX - baseline.positionX) + Math.Abs(cubes[i].positionY - baseline.positionY) + Math.Abs(cubes[i].positionZ - baseline.positionZ) + Math.Abs(cubes[i].linearVelocityX - baseline.linearVelocityX) + Math.Abs(cubes[i].linearVelocityY - baseline.linearVelocityY) + Math.Abs(cubes[i].linearVelocityZ - baseline.linearVelocityZ) + Math.Abs(cubes[i].angularVelocityX - baseline.angularVelocityX) + Math.Abs(cubes[i].angularVelocityY - baseline.angularVelocityY) + Math.Abs(cubes[i].angularVelocityZ - baseline.angularVelocityZ); if (predictedLag < absoluteLag) { int maxPositionLag = absPositionX; if (absPositionY > maxPositionLag) maxPositionLag = absPositionY; if (absPositionZ > maxPositionLag) maxPositionLag = absPositionZ; int maxLinearVelocityLag = absLinearVelocityX; if (absLinearVelocityY > maxLinearVelocityLag) maxLinearVelocityLag = absLinearVelocityY; if (absLinearVelocityZ > maxLinearVelocityLag) maxLinearVelocityLag = absLinearVelocityZ; int maxAngularVelocityLag = absAngularVelocityX; if (absAngularVelocityY > maxAngularVelocityLag) maxAngularVelocityLag = absAngularVelocityY; if (absAngularVelocityZ > maxAngularVelocityLag) maxAngularVelocityLag = absAngularVelocityZ; if (maxPositionLag > PositionDeltaMax || maxLinearVelocityLag > LinearVelocityDeltaMax || maxAngularVelocityLag > AngularVelocityDeltaMax ) continue; hasPrediction[i] = true; cubePredictions[i].positionX = positionLagX; cubePredictions[i].positionY = positionLagY; cubePredictions[i].positionZ = positionLagZ; cubePredictions[i].linearVelocityX = linearVelocityLagX; cubePredictions[i].linearVelocityY = linearVelocityLagY; cubePredictions[i].linearVelocityZ = linearVelocityLagZ; cubePredictions[i].angularVelocityX = angularVelocityLagX; cubePredictions[i].angularVelocityY = angularVelocityLagY; cubePredictions[i].angularVelocityZ = angularVelocityLagZ; } } #endif // #if !DISABLE_DELTA_ENCODING EndSample(); }