コード例 #1
0
    protected void ProcessStateUpdateFromJitterBuffer( Context context, Context.ConnectionData connectionData, int fromClientIndex, int toClientIndex, bool applySmoothing = true )
    {
        if ( connectionData.remoteFrameNumber < 0 )
            return;

        JitterBufferEntry entry = connectionData.jitterBuffer.GetEntry( (uint) connectionData.remoteFrameNumber );
        if ( entry == null )
            return;

        if ( fromClientIndex == 0 )
        {
            // server -> client

            // Ignore updates from before the last reset.
            if ( Network.Util.SequenceGreaterThan( context.GetResetSequence(), entry.packetHeader.resetSequence ) )
                return;

            // Reset if the server reset sequence is more recent than ours.
            if ( Network.Util.SequenceGreaterThan( entry.packetHeader.resetSequence, context.GetResetSequence() ) )
            {
                context.Reset();
                context.SetResetSequence( entry.packetHeader.resetSequence );
            }
        }
        else
        {
            // client -> server

            // Ignore any updates from the client with a different reset sequence #
            if ( context.GetResetSequence() != entry.packetHeader.resetSequence )
                return;
        }

        // add the cube states to the receive delta buffer

        AddPacketToDeltaBuffer( ref connectionData.receiveDeltaBuffer, entry.packetHeader.sequence, context.GetResetSequence(), entry.numStateUpdates, ref entry.cubeIds, ref entry.cubeState );

        // apply the state updates to cubes

        context.ApplyCubeStateUpdates( entry.numStateUpdates, ref entry.cubeIds, ref entry.cubeState, fromClientIndex, toClientIndex, applySmoothing );

        // process the packet header (handles acks)

        connectionData.connection.ProcessPacketHeader( ref entry.packetHeader );
    }
コード例 #2
0
    public bool AddStateUpdatePacket(byte[] packetData, DeltaBuffer receiveDeltaBuffer, ushort resetSequence, out long packetFrameNumber)
    {
        Network.PacketHeader packetHeader;
        ReadStateUpdatePacketHeader(packetData, out packetHeader);

        packetFrameNumber = packetHeader.frameNumber;

        int entryIndex = sequenceBuffer.Insert(packetHeader.frameNumber);

        if (entryIndex < 0)
        {
            return(false);
        }

        bool result = true;

        Profiler.BeginSample("ProcessStateUpdatePacket");

        JitterBufferEntry entry = sequenceBuffer.Entries[entryIndex];

        if (ReadStateUpdatePacket(packetData, out entry.packetHeader, out entry.numAvatarStates, ref entry.avatarStateQuantized, out entry.numStateUpdates, ref entry.cubeIds, ref entry.notChanged, ref entry.hasDelta, ref entry.perfectPrediction, ref entry.hasPredictionDelta, ref entry.baselineSequence, ref entry.cubeState, ref entry.cubeDelta, ref entry.predictionDelta))
        {
            for (int i = 0; i < entry.numAvatarStates; ++i)
            {
                AvatarState.Unquantize(ref entry.avatarStateQuantized[i], out entry.avatarState[i]);
            }

            DecodePrediction(receiveDeltaBuffer, resetSequence, entry.packetHeader.sequence, entry.numStateUpdates, ref entry.cubeIds, ref entry.perfectPrediction, ref entry.hasPredictionDelta, ref entry.baselineSequence, ref entry.cubeState, ref entry.predictionDelta);

            DecodeNotChangedAndDeltas(receiveDeltaBuffer, resetSequence, entry.numStateUpdates, ref entry.cubeIds, ref entry.notChanged, ref entry.hasDelta, ref entry.baselineSequence, ref entry.cubeState, ref entry.cubeDelta);
        }
        else
        {
            sequenceBuffer.Remove(packetHeader.frameNumber);

            result = false;
        }

        Profiler.EndSample();

        return(result);
    }
コード例 #3
0
    public bool GetInterpolatedAvatarState(ref AvatarState[] output, out int numOutputAvatarStates, out ushort resetSequence)
    {
        numOutputAvatarStates = 0;
        resetSequence         = 0;

        // if interpolation frame is negative, it's too early to display anything

        double interpolation_frame = initial_frame + time * Constants.PhysicsFrameRate;

        if (interpolation_frame < 0.0)
        {
            return(false);
        }

        // if we are interpolating but the interpolation start frame is too old,
        // go back to the not interpolating state, so we can find a new start point.

        const int n = 16;

        if (interpolating)
        {
            long frame = (long)Math.Floor(interpolation_frame);

            if (frame - interpolation_start_frame > n)
            {
                interpolating = false;
            }
        }

        // if not interpolating, attempt to find an interpolation start point.
        // if start point exists, go into interpolating mode and set end point to start point
        // so we can reuse code below to find a suitable end point on first time through.
        // if no interpolation start point is found, return.

        if (!interpolating)
        {
            long current_frame = (uint)Math.Floor(interpolation_frame);

            for (long frame = current_frame + 1; (frame > current_frame - n) && (frame >= 0); frame--)
            {
                JitterBufferEntry entry = GetEntry((uint)frame);

                if (entry != null)
                {
                    double avatar_sample_time = (frame - initial_frame) * (1.0 / Constants.PhysicsFrameRate) + entry.packetHeader.avatarSampleTimeOffset;

                    if (time >= avatar_sample_time && time <= avatar_sample_time + (1.0f / Constants.PhysicsFrameRate))
                    {
                        interpolation_start_frame = frame;
                        interpolation_end_frame   = frame;

                        interpolation_start_time = avatar_sample_time;
                        interpolation_end_time   = avatar_sample_time;

                        interpolating = true;
                    }
                }
            }
        }

        if (!interpolating)
        {
            return(false);
        }

        Assert.IsTrue(time >= interpolation_start_time);

        // if current time is >= end time, we need to start a new interpolation
        // from the previous end time to the next sample that exists up to n samples ahead.

        if (time >= interpolation_end_time)
        {
            interpolation_start_frame = interpolation_end_frame;
            interpolation_start_time  = interpolation_end_time;

            for (int i = 0; i < n; ++i)
            {
                JitterBufferEntry entry = GetEntry((uint)(interpolation_start_frame + 1 + i));

                if (entry != null)
                {
                    double avatar_sample_time = (interpolation_start_frame + 1 + i - initial_frame) * (1.0 / Constants.PhysicsFrameRate) + entry.packetHeader.avatarSampleTimeOffset;

                    if (avatar_sample_time >= time)
                    {
                        interpolation_end_frame = interpolation_start_frame + 1 + i;
                        interpolation_end_time  = avatar_sample_time + (1.0 / Constants.PhysicsFrameRate);
                        break;
                    }
                }
            }
        }

        // if current time is still > end time, we couldn't start a new interpolation so return.

        if (time > interpolation_end_time)
        {
            return(false);
        }

        // we are in a valid interpolation, calculate t by looking at current time
        // relative to interpolation start/end times and perform the interpolation.

        float t = (float)Clamp((time - interpolation_start_time) / (interpolation_end_time - interpolation_start_time), 0.0, 1.0);

        JitterBufferEntry a = GetEntry((uint)(interpolation_start_frame));
        JitterBufferEntry b = GetEntry((uint)(interpolation_end_frame));

        for (int i = 0; i < a.numAvatarStates; ++i)
        {
            for (int j = 0; j < b.numAvatarStates; ++j)
            {
                if (a.avatarState[i].client_index == b.avatarState[j].client_index)
                {
                    AvatarState.Interpolate(ref a.avatarState[i], ref b.avatarState[j], out output[numOutputAvatarStates], t);
                    numOutputAvatarStates++;
                }
            }
        }

        resetSequence = a.packetHeader.resetSequence;

        return(true);
    }