/// <summary>
 /// Update the snapshot for an empty frame. Uses the last current target as the new snapshot rather than current rotation.
 /// </summary>
 public void SnapshotEmpty()
 {
     //prevTarget = target;
     target = Localized;
     snapshot = target;
     snapshotTime = Time.time - Time.deltaTime;
 }
    public virtual void Snapshot(List<GenericX> elements, int frameid, bool lateUpdate = false)
    {
        // This safety may no longer be needed. Watch for these errors.
        if (elements[frameid].type == XType.NULL)
        {
            target = Localized;
            snapshot = target;
            Debug.Log("Trying to snapshot a null element genericx ??? ");
            return;
        }

        // First run set both target and snapshot to the incoming.
        if (hasReceivedInitial == false)
        {
            target = elements[frameid];
            hasReceivedInitial = true;
        }

        snapshot = target; // LocalizedRot;
        target = elements[frameid];

        // if this snapshot is being taken due to an overwrite of the current frame mid lerp, leave the time as is.
        if (!lateUpdate)
            snapshotTime = Time.time - Time.deltaTime;
    }
示例#3
0
        public void Teleport(Frame frame)
        {
            int frameid = frame.frameid;
            CompressedElement compressed   = frames[frameid].compXform;
            GenericX          decompressed = frames[frameid].xform;

            // if this is rootRotation, and has an rb that is not isKinematic, make it kinematic temporarily for this teleport
            bool setKinematic = (index == 0 && nst.rb != null && !nst.rb.isKinematic);

            if (setKinematic)
            {
                nst.rb.isKinematic = true;
            }

            Localized          = decompressed;
            lastSentCompressed = compressed;
            lastSentTransform  = decompressed;

            frames[snapshotFrameId].xform = decompressed;
            frames[targetFrameId].xform   = decompressed;

            if (setKinematic)
            {
                nst.rb.isKinematic = false;
            }

            snapshotFrameId = frameid;
            targetFrameId   = frameid;
        }
 public GenericX ExtrapolateRotation(GenericX curr, GenericX prev)
 {
     return new GenericX(
         (extrapolation == 0) ? (Quaternion)curr : QuaternionUtils.ExtrapolateQuaternion(prev, curr, 1 + extrapolation),
         //(extrapolation == 0) ? (Quaternion)curr : Quaternion.SlerpUnclamped(prev, curr, 1),// + extrapolation),
         curr.type);
 }
示例#5
0
        /// <summary>
        /// Apply the rotation inputs, respecting if the moved gameobject is a rigidbody or not. Moves non-kinematic rigidbodies with force,
        /// moves all others with translation. restrictToNstRanges=true will clamp the ranges to the NST and NST Element ranges set for that object,
        /// if any exist. Additionally, even if the objects is a non-kinematic RB, this will still rotate using translate if the rotation type is Euler.
        /// </summary>
        private void ApplyRotation(Vector3 turns)
        {
            // Turn with force only if is a nonKinematic RB and rotation is of the Quat type - otherwise must be moved as euler angles
            if (turnWithForce)
            {
                rb.AddRelativeTorque(turns * turnForce);
                return;
            }

            // Non-Physics-based rotation
            GenericX clamped =
                (restrictToNstRange && re != null && !isQuat) ?
                re.ClampAxes(_gameObject.transform.localEulerAngles + turns * turnRate) :
                _gameObject.transform.localEulerAngles + turns * turnRate;


            if (!isRootGO && re != null)
            {
                re.Apply(clamped);
            }
            // isKinematic ... moverotation otherwise it will studder
            else if (rb == null || translateKinematic)
            {
                _gameObject.transform.localRotation = clamped;
            }
            else
            {
                rb.MoveRotation(clamped);
            }
        }
示例#6
0
 public ElementFrame(GenericX xform, CompressedElement compXform, bool hasChanged, TransformElement transformElement)
 {
     this.xform            = xform;
     this.compXform        = compXform;
     this.hasChanged       = hasChanged;
     this.transformElement = transformElement;
 }
示例#7
0
        public bool Write(ref UdpBitStream bitstream, Frame frame)
        {
            ElementFrame e = frames[frame.frameid];

            e.compXform = Compress();
            e.xform     = Localized;

            CompressedElement newComp = e.compXform;

            bool forceUpdate = IsUpdateForced(frame);

            // For frames between forced updates, we need to first send a flag bit for if this element is being sent
            if (!forceUpdate)
            {
                bool hasChanged = !CompressedElement.Compare(newComp, lastSentCompressed) && sendCullMask.OnChanges();
                bitstream.WriteBool(hasChanged);

                // if no changes have occured we are done.
                if (!hasChanged)
                {
                    return(false);
                }
            }

            crusher.Write(e.compXform, bitstream.Data, ref bitstream.ptr);

            lastSentCompressed = newComp;
            lastSentTransform  = e.xform;

            return(true);
        }
        public void Initialize(NetworkSyncTransform _nst, INSTTransformElement _nstElement)
        {
            nst        = _nst;
            nstElement = _nstElement;

            na = nst.na ? nst.na : (nst.na = nst.GetComponent <NSTNetAdapter>());

            frameCount = NSTMaster.FRAME_COUNT / nst.sendEveryXTick;

            //// TODO: Would rather not have to do this here - but the automation for this isn't firing in time
            //crusher.CacheValues();

            frames = new ElementFrame[frameCount + 1];
            for (int i = 0; i < frames.Length; i++)
            {
                var ce = new CompressedElement();
                Compress(ce);
                frames[i] = new ElementFrame(Localized, ce, false, this);
            }

            history = new GenericX[frameCount + 1];
            for (int i = 0; i < history.Length; i++)
            {
                history[i] = new GenericX();
            }

            Compress(lastSentCompressed);
            lastSentTransform = Localized;
        }
示例#9
0
        public override GenericX Extrapolate(GenericX curr, GenericX prev)
        {
            if (curr.type == XType.NULL)
            {
                Debug.Log("Extrap pos element NULL !! Try to eliminate these Davin");
                return(Localized);
            }
            if (crusher.TRSType == TRSType.Quaternion)
            {
                return(new GenericX(
                           (extrapolation == 0) ? (Quaternion)curr : QuaternionUtils.ExtrapolateQuaternion(prev, curr, 1 + extrapolation), curr.type));
            }
            else
            {
                if (extrapolation == 0)
                {
                    return(curr);
                }

                Quaternion extrapolated = QuaternionUtils.ExtrapolateQuaternion(prev, curr, 1 + extrapolation);

                // Test for the rare nasty (NaN, Nan, Nan, NaN) occurance... and deal with it
                if (float.IsNaN(extrapolated[0]))
                {
                    return(curr);
                }

                return(new GenericX(extrapolated.eulerAngles, curr.type));
            }
        }
示例#10
0
        /// <summary>
        /// Copy one frame to another. Used when the buffer is empty and either need to copy the current frame or resort to the offtick frame.
        /// </summary>
        public void CopyFrame(Frame sourceFrame, Frame targetFrame, bool includePositions = true, bool includeRotations = true)
        {
            targetFrame.pos = sourceFrame.pos;

            targetFrame.compPos     = sourceFrame.compPos;
            targetFrame.endTime     = sourceFrame.endTime;
            targetFrame.appliedTime = sourceFrame.appliedTime;
            // Strip the custom message flag from copies, or they will fire twice.
            targetFrame.msgType = (sourceFrame.msgType == MsgType.Cust_Msg) ? MsgType.Position : sourceFrame.msgType;

            if (includePositions)
            {
                targetFrame.positionsMask = sourceFrame.positionsMask;
                for (int i = 0; i < targetFrame.positions.Count; i++)
                {
                    GenericX.Copy(sourceFrame.positions[i], targetFrame.positions[i]);
                    DebugX.Log(Time.time + " " + i + " Copy Source Pos " + sourceFrame.positions[i]);
                }
            }

            if (includeRotations)
            {
                targetFrame.rotationsMask = sourceFrame.rotationsMask;
                for (int i = 0; i < targetFrame.rotations.Count; i++)
                {
                    GenericX.Copy(sourceFrame.rotations[i], targetFrame.rotations[i]);
                    DebugX.Log(Time.time + " " + i + " Copy Source Rot " + sourceFrame.rotations[i]);
                }
            }
            targetFrame.packetArriveTime = Time.time;
        }
示例#11
0
        public void Teleport(CompressedElement compressed, GenericX decompressed)
        {
            // if this is rootRotation, and has an rb that is not isKinematic, make it kinematic temporarily for this teleport
            bool setKinematic = (index == 0 && nst.rb != null && !nst.rb.isKinematic);

            if (setKinematic)
            {
                nst.rb.isKinematic = true;
            }

            Localized          = decompressed;
            lastSentCompressed = compressed;
            lastSentTransform  = decompressed;

            if (snapshot != null)
            {
                snapshot.elements[index].transform = decompressed;
            }

            if (target != null)
            {
                target.elements[index].transform = decompressed;
            }

            if (setKinematic)
            {
                nst.rb.isKinematic = false;
            }
        }
示例#12
0
文件: Frame.cs 项目: vert0r/NetDemo2
 public XElement(GenericX transform, CompressedElement compTrans, bool hasChanged, TransformElement transformElement)
 {
     this.transform        = transform;
     this.compTrans        = compTrans;
     this.hasChanged       = hasChanged;
     this.transformElement = transformElement;
 }
示例#13
0
        public void Initialize(NetworkSyncTransform _nst)
        {
            nst = _nst;
            na  = nst.na ? nst.na : (nst.na = nst.GetComponent <NSTNetAdapter>());

            frameCount = 60 / nst.sendEveryXTick;

            cache_axisEnabled = new bool[3];
            for (int i = 0; i < 3; ++i)
            {
                cache_axisEnabled[i] = crusher[i].Enabled;
            }

            frames = new ElementFrame[frameCount + 1];
            for (int i = 0; i < frames.Length; i++)
            {
                frames[i] = new ElementFrame(Localized, Compress(), false, this);
            }

            history = new GenericX[frameCount + 1];
            for (int i = 0; i < history.Length; i++)
            {
                history[i] = new GenericX();
            }

            lastSentCompressed = Compress();
            lastSentTransform  = Localized;
        }
示例#14
0
 // Apply position without overwriting unused axis with zero.
 public void ApplyPosition(Vector3 pos)
 {
     //gameobject.transform.localPosition = pos;
     Localized = new Vector3(
         (axisRanges[0].useAxis) ? pos[0] : Localized[0],
         (axisRanges[1].useAxis) ? pos[1] : Localized[1],
         (axisRanges[2].useAxis) ? pos[2] : Localized[2]);
 }
示例#15
0
        public NSTElementsEngine Initialize()
        {
            if (initialized)
            {
                return(this);
            }

            initialized = true;

            // Collect all of the transform elements
            INSTTransformElement[] iTransElement = GetComponentsInChildren <INSTTransformElement>(true);
            elementIdLookup = new Dictionary <string, int>(iTransElement.Length);
            elementLookup   = new Dictionary <string, TransformElement>(iTransElement.Length);

            transformElements = new TransformElement[iTransElement.Length];
            for (int i = 0; i < iTransElement.Length; i++)
            {
                if (elementIdLookup.ContainsKey(iTransElement[i].TransElement.name))
                {
                    DebugX.LogError(!DebugX.logErrors ? "" :
                                    ("Multiple child elements with the same name on '" + nst.name + "'. Check the names of Rotation and Positon elements for any repeats and be sure they all have unique names."));
                }
                else
                {
                    elementIdLookup.Add(iTransElement[i].TransElement.name, i);
                    elementLookup.Add(iTransElement[i].TransElement.name, iTransElement[i].TransElement);
                }

                // Make note of which of the transforms belongs to the NST root rotation
                if (transformElements[i] == nst.rootRotationElement)
                {
                    rootRotId            = i;
                    transformElements[0] = transformElements[i];
                }

                transformElements[i]       = iTransElement[i].TransElement;
                transformElements[i].index = i;

                if (transformElements[i].gameobject == null)
                {
                    transformElements[i].gameobject = iTransElement[i].GameObject;
                }

                transformElements[i].Initialize(nst);
            }

            // init the list
            history = new GenericX[NSTSettings.single.frameCount][];
            for (int frameid = 0; frameid < history.Length; frameid++)
            {
                history[frameid] = new GenericX[transformElements.Length];
                for (int elementid = 0; elementid < transformElements.Length; elementid++)
                {
                    history[frameid][elementid] = new GenericX();
                }
            }
            return(this);
        }
    public GenericX Extrapolate(GenericX curr, GenericX prev)
    {
        //Debug.Log(Time.time +  " Extrapolating element for missing frame prev:" + prev + " curr " + curr + " res " + (curr + (curr - prev) * extrapolation));

        //if (prev == curr)
        //	Debug.Log(nst.name + " NO CHANGE ");

        return
            (extrapolation == 0) ? curr :
            curr + (curr - prev) * extrapolation;
    }
示例#17
0
 public override GenericX Lerp(GenericX start, GenericX end, float t)
 {
     if (start.type == XType.Quaternion)
     {
         return(Quaternion.Slerp(start, end, t));
     }
     else
     {
         return(Quaternion.Slerp(start, end, t).eulerAngles);
     }
 }
 public void Compress(CompressedElement target, GenericX uncompressed)
 {
     if (crusher.TRSType == TRSType.Quaternion)
     {
         crusher.Compress(target, (Quaternion)uncompressed);
     }
     else
     {
         crusher.Compress(target, (Vector3)uncompressed);
     }
 }
示例#19
0
 /// <summary>
 /// Apply a rotation to a gameobject, respecting this elements useLocal and axis restrictions
 /// </summary>
 public void Apply(GenericX val, GameObject targetGO)
 {
     if (crusher.TRSType == TRSType.Quaternion)
     {
         crusher.Apply(targetGO.transform, new Element((Quaternion)val));
     }
     else
     {
         crusher.Apply(targetGO.transform, (Vector3)val);
     }
 }
示例#20
0
 public CompressedElement Compress(GenericX uncompressed)
 {
     if (crusher.TRSType == TRSType.Quaternion)
     {
         return(crusher.Compress((Quaternion)uncompressed));
     }
     else
     {
         return(crusher.Compress((Vector3)uncompressed));
     }
 }
示例#21
0
 public GenericX Lerp(GenericX start, GenericX end, float t)
 {
     if (crusher.TRSType == TRSType.Quaternion)
     {
         return(Quaternion.Slerp(start, end, t));
     }
     else if (crusher.TRSType == TRSType.Euler)
     {
         return(Quaternion.Slerp(start, end, t).eulerAngles);
     }
     else
     {
         return(Vector3.Lerp(start, end, t));
     }
 }
示例#22
0
 public override CompressedElement Compress(GenericX uncompressed)
 {
     if (rotationType == RotationType.Quaternion)
     {
         return(QuatCompress.CompressQuatToBitsBuffer(uncompressed, totalBitsForQuat));
     }
     else
     {
         return(new CompressedElement(
                    (includedAxes.IsX()) ? CompressFloat(uncompressed[0], 0) : 0,
                    (includedAxes.IsY()) ? CompressFloat(uncompressed[1], 1) : 0,
                    (includedAxes.IsZ()) ? CompressFloat(uncompressed[2], 2) : 0
                    ));
     }
 }
示例#23
0
        public CompressedElement CompressElement(GenericX uncompressed)
        {
            CompressedElement newCPos = new CompressedElement();

            for (int axis = 0; axis < 3; axis++)
            {
                newCPos[axis] = (axisRanges[axis].useAxis) ?
                                (compression == Compression.HalfFloat) ? SlimMath.HalfUtilities.Pack(uncompressed[axis]) :
                                //(compression == Compression.Global) ? uncompressed[axis].CompressAxis(axis) :
                                (compression == Compression.LocalRange) ? axisRanges[axis].Encode(uncompressed[axis]) :
                                ((UdpKit.UdpByteConverter)uncompressed[axis]).Unsigned32 : 0;
            }

            return(newCPos);
        }
        public bool Write(ref UdpBitStream bitstream, Frame frame)
        {
            ElementFrame      e         = frames[frame.frameid];
            CompressedElement compXform = e.compXform;

            Compress(compXform);
            e.xform = Decompress(compXform);             // Localized;

            /// Experimental - Apply the outgoing lossy values to the GhostGO so owner/authority of object can use it to replicate lossy events like weapon fire.
            if (ghostGO)
            {
                Apply(e.xform, ghostGO);
            }

            if (!nstElement.Enabled)
            {
                bitstream.WriteBool(false);
                return(false);
            }

            bool forceUpdate = IsUpdateForced(frame);

            // For frames between forced updates, we need to first send a flag bit for if this element is being sent
            if (!forceUpdate)
            {
                bool hasChanged = !compXform.Equals(lastSentCompressed) && sendCullMask.OnChanges();
                bitstream.WriteBool(hasChanged);

                // if no changes have occured we are done.
                if (!hasChanged)
                {
                    return(false);
                }
            }
            else
            {
                bitstream.WriteBool(true);
            }

            crusher.Write(compXform, bitstream.Data, ref bitstream.ptr);

            lastSentCompressed.CopyFrom(compXform);
            lastSentTransform = e.xform;

            return(true);
        }
示例#25
0
        public virtual void Initialize(NetworkSyncTransform _nst)
        {
            nst        = _nst;
            na         = _nst.na;
            frameCount = nst.frameCount;

            frames = new ElementFrame[frameCount + 1];
            for (int i = 0; i < frames.Length; i++)
            {
                frames[i] = new ElementFrame(Localized, Compress(), false, this);
            }

            history = new GenericX[frameCount + 1];
            for (int i = 0; i < history.Length; i++)
            {
                history[i] = new GenericX();
            }
        }
        /// <summary>
        /// Apply the rotation inputs, respecting if the moved gameobject is a rigidbody or not. Moves non-kinematic rigidbodies with force,
        /// moves all others with translation. restrictToNstRanges=true will clamp the ranges to the NST and NST Element ranges set for that object,
        /// if any exist. Additionally, even if the objects is a non-kinematic RB, this will still rotate using translate if the rotation type is Euler.
        /// </summary>
        private void ApplyRotation(Vector3 turns)
        {
            bool local = (re == null || (re as RotationElement).crusher.local);

            // Turn with force only if is a nonKinematic RB and rotation is of the Quat type - otherwise must be moved as euler angles
            if (turnWithForce)
            {
                rb.AddRelativeTorque(turns * turnForce);
                return;
            }

            GenericX unclamped =
                (isRootGO || !local) ?
                _gameObject.transform.eulerAngles + turns * turnRate :
                _gameObject.transform.localEulerAngles + turns * turnRate;

            // Non-Physics-based rotation
            GenericX clamped = (restrictToNstRange && re != null && !isQuat) ?
                               re.GetCorrectedForOutOfBounds(unclamped) :
                               (Vector3)unclamped;


            if (!isRootGO && re != null)
            {
                re.Apply(clamped);
            }
            // isKinematic ... moverotation otherwise it will studder
            else if (rb == null || translateKinematic)
            {
                if (local)
                {
                    _gameObject.transform.localRotation = clamped;
                }
                else
                {
                    _gameObject.transform.rotation = clamped;
                }
            }

            else
            {
                rb.MoveRotation(clamped);
            }
        }
        public void Teleport(Frame frame)
        {
            int       frameid = frame.frameid;
            Rigidbody rb      = nst.rb;

            CompressedElement compressed   = frames[frameid].compXform;
            GenericX          decompressed = frames[frameid].xform;

            // if this is rootRotation, and has an rb that is not isKinematic, make it kinematic temporarily for this teleport
            bool setKinematic = (index == 0 && rb != null && !rb.isKinematic);
            bool wasKinematic;

            if (setKinematic)
            {
                wasKinematic   = rb.isKinematic;
                rb.isKinematic = true;
            }
            else
            {
                wasKinematic = false;
            }

            Localized = decompressed;

            lastSentCompressed.CopyFrom(compressed);
            lastSentTransform = decompressed;

            frames[snapshotFrameId].xform = decompressed;
            compressed.CopyFrom(compressed);

            frames[targetFrameId].xform = decompressed;
            frames[targetFrameId].compXform.CopyFrom(compressed);

            if (setKinematic)
            {
                rb.isKinematic = wasKinematic;
            }

            //snapshotFrameId = frameid;
            //targetFrameId = frameid;
        }
示例#28
0
        /// <summary>
        /// Apply a rotation to a gameobject, respecting this elements useLocal and axis restrictions
        /// </summary>
        public override void Apply(GenericX rot, GameObject targetGO)
        {
            int type = (int)xtype;

            if (useLocal)
            {
                if (rot.type == XType.Quaternion)
                {
                    targetGO.transform.localRotation = rot;
                }
                else
                {
                    targetGO.transform.localRotation =
                        Quaternion.Euler(
                            ((type & 1) != 0) ? rot.x : targetGO.transform.localEulerAngles.x,
                            ((type & 2) != 0) ? rot.y : targetGO.transform.localEulerAngles.y,
                            ((type & 4) != 0) ? rot.z : targetGO.transform.localEulerAngles.z
                            );
                }
            }
            else
            {
                if (rot.type == XType.Quaternion)
                {
                    targetGO.transform.rotation = rot;
                }
                else
                {
                    targetGO.transform.eulerAngles =
                        new Vector3(
                            ((type & 1) != 0) ? rot.x : targetGO.transform.eulerAngles.x,
                            ((type & 2) != 0) ? rot.y : targetGO.transform.eulerAngles.y,
                            ((type & 4) != 0) ? rot.z : targetGO.transform.eulerAngles.z
                            );
                }
            }


            //rot.ApplyRotation(targetGO.transform, useLocal);
        }
示例#29
0
        public void ExtrapolateNextFrame(Frame curr, Frame prev, Frame target)
        {
            //target.compPos = CompressedV3.Extrapolate(curr.compPos, prev.compPos, nst.extrapolation);
            target.pos = Vector3.Lerp(curr.pos, curr.pos + (curr.pos - prev.pos), nst.extrapolation);

            DebugX.Log(Time.time + " " + nst.name + " <color=black>Extrapolated Missing Next Frame targ:" + target.compPos + " curr:" + curr.compPos + " prev" + prev.compPos + "</color>");

            target.compPos = target.pos.CompressPos();
            target.msgType = (curr.msgType == MsgType.Cust_Msg) ? MsgType.Position : curr.msgType;


            //TODO: need to limit the number of extrapolation iterations can occur.

            // Position Elements
            target.positionsMask = curr.positionsMask;
            for (int i = 0; i < target.positions.Count; i++)
            {
                GenericX currTarget = nst.positionElements[i].target;
                GenericX prevTarget = nst.positionElements[i].snapshot;

                target.positions[i] = nst.positionElements[i].Extrapolate(currTarget, prevTarget);
                //i.SetBitInMask(ref target.positionsMask, false);
            }

            // TODO: extrapolate rotations?
            target.rotationsMask = curr.rotationsMask;
            for (int i = 0; i < target.rotations.Count; i++)
            {
                GenericX currTarget = nst.rotationElements[i].target;
                GenericX prevTarget = nst.rotationElements[i].snapshot;
                //Debug.Log(" ExtrapolateNextFrame " + curr.rotations[i] + " -- > " + target.rotations[i]);
                target.rotations[i] = nst.rotationElements[i].ExtrapolateRotation(currTarget, prevTarget);
                //target.rotations[i] = nst.rotationElements[i].Extrapolate(curr.rotations[i], prev.rotations[i]);
                //TEST
                target.rotations[i] = QuaternionUtils.ExtrapolateQuaternion(prevTarget, currTarget, 2f);
                i.SetBitInMask(ref target.rotationsMask, true);
            }
        }
示例#30
0
 public abstract GenericX Extrapolate(GenericX curr, GenericX prev);