Exemple #1
0
        public static void ConstructTransformFromMatrixWithDesiredScale(FMatrix aMatrix, FMatrix bMatrix,
                                                                        FVector desiredScale, ref FTransform outTransform)
        {
            // the goal of using M is to get the correct orientation
            // but for translation, we still need scale
            var m = aMatrix * bMatrix;

            m.RemoveScaling();

            // apply negative scale back to axes
            var signedScale = desiredScale.GetSignVector();

            m.SetAxis(0, m.GetScaledAxis(EAxis.X) * signedScale.X);
            m.SetAxis(1, m.GetScaledAxis(EAxis.Y) * signedScale.Y);
            m.SetAxis(2, m.GetScaledAxis(EAxis.Z) * signedScale.Z);

            // @note: if you have negative with 0 scale, this will return rotation that is identity
            // since matrix loses that axes
            var rotation = new FQuat(m);

            rotation.Normalize();

            // set values back to output
            outTransform.Scale3D  = desiredScale;
            outTransform.Rotation = rotation;

            // technically I could calculate this using FTransform but then it does more quat multiplication
            // instead of using Scale in matrix multiplication
            // it's a question of between RemoveScaling vs using FTransform to move translation
            outTransform.Translation = m.GetOrigin();
        }
Exemple #2
0
        public static FMat4 FromQuaternion(FQuat quaternion)
        {
            FVec4 squared = new FVec4(quaternion.x * quaternion.x, quaternion.y * quaternion.y, quaternion.z * quaternion.z,
                                      quaternion.w * quaternion.w);
            Fix64 invSqLength = Fix64.One / (squared.x + squared.y + squared.z + squared.w);

            Fix64 temp1 = quaternion.x * quaternion.y;
            Fix64 temp2 = quaternion.z * quaternion.w;
            Fix64 temp3 = quaternion.x * quaternion.z;
            Fix64 temp4 = quaternion.y * quaternion.w;
            Fix64 temp5 = quaternion.y * quaternion.z;
            Fix64 temp6 = quaternion.x * quaternion.w;

            return(new FMat4
                   (
                       new FVec4((squared.x - squared.y - squared.z + squared.w) * invSqLength,
                                 Fix64.Two * (temp1 + temp2) * invSqLength,
                                 Fix64.Two * (temp3 - temp4) * invSqLength,
                                 Fix64.Zero),
                       new FVec4(Fix64.Two * (temp1 - temp2) * invSqLength,
                                 (-squared.x + squared.y - squared.z + squared.w) * invSqLength,
                                 Fix64.Two * (temp5 + temp6) * invSqLength,
                                 Fix64.Zero),
                       new FVec4(Fix64.Two * (temp3 + temp4) * invSqLength,
                                 Fix64.Two * (temp5 - temp6) * invSqLength,
                                 (-squared.x - squared.y + squared.z + squared.w) * invSqLength,
                                 Fix64.Zero),
                       new FVec4(Fix64.Zero, Fix64.Zero, Fix64.Zero, Fix64.One)
                   ));
        }
        /// <summary>
        /// Reads out the expression from a BinaryReader.
        /// </summary>
        /// <param name="reader">The BinaryReader to read from.</param>
        public override void Read(AssetBinaryReader reader)
        {
            var rotation    = new FQuat(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            var translation = new FVector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            var scale       = new FVector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

            Value = new FTransform(rotation, translation, scale);
        }
Exemple #4
0
        /// <summary>
        /// Tries to move the component by a movement vector (Delta) and sets rotation to NewRotation.
        /// Assumes that the component's current location is valid and that the component does fit in its current Location.
        /// Dispatches blocking hit notifications (if bSweep is true), and calls UpdateOverlaps() after movement to update overlap state.
        ///
        /// <para/>@note This simply calls the virtual MoveComponentImpl() which can be overridden to implement custom behavior.
        /// <para/>@note The overload taking rotation as an FQuat is slightly faster than the version using FRotator (which will be converted to an FQuat)..
        /// </summary>
        /// <param name="delta">The desired location change in world space.</param>
        /// <param name="newRotation">The new desired rotation in world space.</param>
        /// <param name="sweep">Whether we sweep to the destination location, triggering overlaps along the way and stopping short of the target if blocked by something.
        /// Only the root component is swept and checked for blocking collision, child components move without sweeping. If collision is off, this has no effect.</param>
        /// <param name="hit">Optional output describing the blocking hit that stopped the move, if any.</param>
        /// <param name="moveFlags">Flags controlling behavior of the move. @see EMoveComponentFlags</param>
        /// <param name="teleport">Determines whether to teleport the physics body or not. Teleporting will maintain constant velocity and avoid collisions along the path</param>
        /// <returns>True if some movement occurred, false if no movement occurred.</returns>
        public unsafe bool MoveComponent(FVector delta, FQuat newRotation, bool sweep, out FHitResult hit, EMoveComponentFlags moveFlags = EMoveComponentFlags.NoFlags, ETeleportType teleport = ETeleportType.None)
        {
            byte *buff   = stackalloc byte[StructDefault <FHitResult> .Size];
            bool  result = Native_USceneComponent.MoveComponentQuat(this.Address, ref delta, ref newRotation, sweep, (IntPtr)buff, (int)moveFlags, (int)teleport);

            hit = new FHitResult((IntPtr)buff);
            return(result);
        }
Exemple #5
0
        public static FMat4 FromTRS(FVec3 pos, FQuat q, FVec3 scale)
        {
            FMat4 m = FromScale(scale) * FromQuaternion(q);

            m.w.x = pos.x;
            m.w.y = pos.y;
            m.w.z = pos.z;
            return(m);
        }
Exemple #6
0
        public FQuatRotationTranslationMatrix(FQuat q, FVector origin)
        {
            var x2 = q.X + q.X;  var y2 = q.Y + q.Y;  var z2 = q.Z + q.Z;
            var xx = q.X * x2;   var xy = q.X * y2;   var xz = q.X * z2;
            var yy = q.Y * y2;   var yz = q.Y * z2;   var zz = q.Z * z2;
            var wx = q.W * x2;   var wy = q.W * y2;   var wz = q.W * z2;

            M00 = 1.0f - (yy + zz);     M10 = xy - wz;                  M20 = xz + wy;                  M30 = origin.X;
            M01 = xy + wz;                      M11 = 1.0f - (xx + zz); M21 = yz - wx;                  M31 = origin.Y;
            M02 = xz - wy;                      M12 = yz + wx;                  M22 = 1.0f - (xx + yy); M32 = origin.Z;
            M03 = 0.0f;                         M13 = 0.0f;                             M23 = 0.0f;                             M33 = 1.0f;
        }
Exemple #7
0
        public void Matrix3()
        {
            FMat3 fm  = FMat3.FromQuaternion(FQuat.Euler(( Fix64 )30, ( Fix64 )(-20), ( Fix64 )49.342f));
            Mat3  m   = Mat3.FromQuaternion(Quat.Euler(30, -20, 49.342f));
            FVec3 fv  = new FVec3(12.5f, 9, 8);
            FVec3 fv2 = new FVec3(4, 6, 9);
            Vec3  v   = new Vec3(12.5f, 9, 8);
            Vec3  v2  = new Vec3(4, 6, 9);

            fv  = fm.TransformPoint(fv);
            fv2 = fm.TransformVector(fv2);
            v   = m.TransformPoint(v);
            v2  = m.TransformVector(v2);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            this._output.WriteLine(fv.ToString());
            this._output.WriteLine(fv2.ToString());
            this._output.WriteLine(v.ToString());
            this._output.WriteLine(v2.ToString());
            fm = FMat3.LookAt(fv, fv2);
            m  = Mat3.LookAt(v, v2);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fv = fm.Euler();
            v  = m.Euler();
            this._output.WriteLine(fv.ToString());
            this._output.WriteLine(v.ToString());
            fm = FMat3.FromEuler(fv);
            m  = Mat3.FromEuler(v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat3.FromScale(fv);
            m  = Mat3.FromScale(v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat3.FromCross(fv);
            m  = Mat3.FromCross(v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat3.FromOuterProduct(fv, fv2);
            m  = Mat3.FromOuterProduct(v, v2);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat3.FromRotationAxis(( Fix64 )35, fv);
            m  = Mat3.FromRotationAxis(35, v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat3.NonhomogeneousInverse(fm);
            m  = Mat3.NonhomogeneousInvert(m);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
        }
Exemple #8
0
        public FMat3 RotateAround(Fix64 angle, FVec3 axis)
        {
            // rotate into world space
            FQuat quaternion       = FQuat.AngleAxis(Fix64.Zero, axis).Conjugate();
            FMat3 worldSpaceMatrix = FromQuaternion(quaternion) * this;

            // rotate back to matrix space
            quaternion = FQuat.AngleAxis(angle, axis);
            FMat3 qMat = FromQuaternion(quaternion);

            worldSpaceMatrix = qMat * worldSpaceMatrix;
            return(worldSpaceMatrix);
        }
Exemple #9
0
        private static void ReadPerTrackQuatData(FArchive Ar, string trackKind, ref FQuat[] dstKeys, ref float[] dstTimeKeys, int numFrames)
        {
            var packedInfo    = Ar.Read <uint>();
            var keyFormat     = (AnimationCompressionFormat)(packedInfo >> 28);
            var componentMask = (int)((packedInfo >> 24) & 0xF);
            var numKeys       = (int)(packedInfo & 0xFFFFFF);
            var hasTimeTracks = (componentMask & 8) != 0;

            var mins   = FVector.ZeroVector;
            var ranges = FVector.ZeroVector;

            dstKeys = new FQuat[numKeys];
            if (keyFormat == ACF_IntervalFixed32NoW)
            {
                // read mins/maxs
                if ((componentMask & 1) != 0)
                {
                    mins.X   = Ar.Read <float>();
                    ranges.X = Ar.Read <float>();
                }
                if ((componentMask & 2) != 0)
                {
                    mins.Y   = Ar.Read <float>();
                    ranges.Y = Ar.Read <float>();
                }
                if ((componentMask & 4) != 0)
                {
                    mins.Z   = Ar.Read <float>();
                    ranges.Z = Ar.Read <float>();
                }
            }
            for (var keyIndex = 0; keyIndex < numKeys; keyIndex++)
            {
                dstKeys[keyIndex] = keyFormat switch
                {
                    ACF_None or ACF_Float96NoW => Ar.ReadQuatFloat96NoW(),
                                ACF_Fixed48NoW => Ar.ReadQuatFixed48NoW(componentMask),
                    ACF_Fixed32NoW => Ar.ReadQuatFixed32NoW(),
                    ACF_IntervalFixed32NoW => Ar.ReadQuatIntervalFixed32NoW(mins, ranges),
                    ACF_Float32NoW => Ar.ReadQuatFloat32NoW(),
                    ACF_Identity => FQuat.Identity,
                    _ => throw new ParserException(Ar, $"Unknown {trackKind} compression method: {(int) keyFormat} ({keyFormat})")
                };
            }
            // align to 4 bytes
            Ar.Position = Ar.Position.Align(4);
            if (hasTimeTracks)
            {
                ReadTimeArray(Ar, numKeys, out dstTimeKeys, numFrames);
            }
        }
Exemple #10
0
        public void Matrix4()
        {
            FMat4 fm  = FMat4.FromQuaternion(FQuat.Euler(( Fix64 )30, ( Fix64 )(-20), ( Fix64 )49.342f));
            Mat4  m   = Mat4.FromQuaternion(Quat.Euler(30, -20, 49.342f));
            FVec3 fv  = new FVec3(12.5f, 9, 8);
            FVec3 fv2 = new FVec3(4, 6, 9);
            Vec3  v   = new Vec3(12.5f, 9, 8);
            Vec3  v2  = new Vec3(4, 6, 9);

            fv  = fm.TransformPoint(fv);
            fv2 = fm.TransformVector(fv2);
            v   = m.TransformPoint(v);
            v2  = m.TransformVector(v2);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            this._output.WriteLine(fv.ToString());
            this._output.WriteLine(fv2.ToString());
            this._output.WriteLine(v.ToString());
            this._output.WriteLine(v2.ToString());
            fm = FMat4.FromEuler(fv);
            m  = Mat4.FromEuler(v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat4.FromScale(fv);
            m  = Mat4.FromScale(v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat4.FromRotationAxis(( Fix64 )35, fv);
            m  = Mat4.FromRotationAxis(35, v);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat4.NonhomogeneousInverse(fm);
            m  = Mat4.NonhomogeneousInvert(m);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat4.FromTRS(new FVec3(4, 5, 6), FQuat.identity, FVec3.one);
            m  = Mat4.FromTRS(new Vec3(4, 5, 6), Quat.identity, Vec3.one);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fm = FMat4.NonhomogeneousInverse(fm);
            m  = Mat4.NonhomogeneousInvert(m);
            this._output.WriteLine(fm.ToString());
            this._output.WriteLine(m.ToString());
            fv = fm.TransformPoint(fv);
            v  = m.TransformPoint(v);
            this._output.WriteLine(fv.ToString());
            this._output.WriteLine(v.ToString());
        }
Exemple #11
0
        public static NodeBuilder[] CreateGltfSkeleton(List <CSkelMeshBone> skeleton, NodeBuilder armatureNode) // TODO optimize
        {
            var result = new List <NodeBuilder>();

            for (var i = 0; i < skeleton.Count; i++)
            {
                var root = skeleton[i];
                if (root.ParentIndex != -1)
                {
                    continue;
                }

                var rootCopy = (CSkelMeshBone)root.Clone(); // we don't want to modify the original skeleton
                rootCopy.Orientation = FQuat.Conjugate(root.Orientation);
                result.AddRange(CreateBonesRecursive(rootCopy, armatureNode, skeleton, i));
            }

            return(result.ToArray());
        }
Exemple #12
0
 public FQuatRotationMatrix(FQuat q) : base(q, FVector.ZeroVector)
 {
 }
Exemple #13
0
 /// <summary>
 /// Adds a delta to the rotation of the component in world space.
 /// </summary>
 /// <param name="deltaRotation">Change in rotation in world space for the component.</param>
 /// <param name="sweep">Whether we sweep to the destination (currently not supported for rotation).</param>
 /// <param name="teleport">Whether we teleport the physics state (if physics collision is enabled for this object).
 /// If true, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
 /// If false, physics velocity is updated based on the change in position (affecting ragdoll parts).
 /// If CCD is on and not teleporting, this will affect objects along the entire sweep volume.</param>
 public void AddWorldRotation(FQuat deltaRotation, bool sweep = false, ETeleportType teleport = ETeleportType.None)
 {
     Native_USceneComponent.AddWorldRotationQuat(this.Address, ref deltaRotation, sweep, (int)teleport);
 }
Exemple #14
0
 public bool MoveComponent(FVector delta, FQuat newRotation, bool sweep, EMoveComponentFlags moveFlags = EMoveComponentFlags.NoFlags, ETeleportType teleport = ETeleportType.None)
 {
     return(Native_USceneComponent.MoveComponentQuatNoHit(this.Address, ref delta, ref newRotation, sweep, (int)moveFlags, (int)teleport));
 }
Exemple #15
0
        public static FMat4 FromRotationAxis(Fix64 angle, FVec3 axis)
        {
            FQuat quaternion = FQuat.AngleAxis(angle, axis);

            return(FromQuaternion(quaternion));
        }
Exemple #16
0
 /// <summary>
 /// Set the actor's RootComponent to the specified relative rotation
 /// </summary>
 /// <param name="NewRelativeRotation">New relative rotation of the actor's root component</param>
 /// <param name="sweep">Whether we sweep to the destination location, triggering overlaps along the way and stopping short of the target if blocked by something.
 /// Only the root component is swept and checked for blocking collision, child components move without sweeping. If collision is off, this has no effect.</param>
 /// <param name="teleport">Whether we teleport the physics state (if physics collision is enabled for this object).
 /// If true, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
 /// If false, physics velocity is updated based on the change in position (affecting ragdoll parts).
 /// If CCD is on and not teleporting, this will affect objects along the entire swept volume.</param>
 public void SetActorRelativeRotation(FQuat newRelativeRotation, bool sweep = false, ETeleportType teleport = ETeleportType.None)
 {
     Native_AActor.SetActorRelativeRotationQuat(this.Address, ref newRelativeRotation, sweep, (int)teleport);
 }
Exemple #17
0
 /// <summary>
 /// Adds a delta to the rotation of this component in its local reference frame
 /// </summary>
 /// <param name="deltaRotation">The change in rotation in local space.</param>
 /// <param name="sweep">Whether we sweep to the destination location, triggering overlaps along the way and stopping short of the target if blocked by something.
 /// Only the root component is swept and checked for blocking collision, child components move without sweeping. If collision is off, this has no effect.
 /// Whether we teleport the physics state (if physics collision is enabled for this object).</param>
 /// <param name="teleport">If true, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
 /// If false, physics velocity is updated based on the change in position (affecting ragdoll parts).
 /// If CCD is on and not teleporting, this will affect objects along the entire swept volume.</param>
 public void AddActorLocalRotation(FQuat deltaRotation, bool sweep = false, ETeleportType teleport = ETeleportType.None)
 {
     Native_AActor.AddActorLocalRotationQuat(this.Address, ref deltaRotation, sweep, (int)teleport);
 }
Exemple #18
0
 /// <summary>
 /// Move the actor instantly to the specified location and rotation.
 /// </summary>
 /// <param name="newLocation">The new location to teleport the Actor to.</param>
 /// <param name="newRotation">The new rotation for the Actor.</param>
 /// <param name="sweep">Whether we sweep to the destination location, triggering overlaps along the way and stopping short of the target if blocked by something.
 /// Only the root component is swept and checked for blocking collision, child components move without sweeping. If collision is off, this has no effect.</param>
 /// <param name="teleport">How we teleport the physics state (if physics collision is enabled for this object).
 /// If equal to ETeleportType::TeleportPhysics, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
 /// If equal to ETeleportType::None, physics velocity is updated based on the change in position (affecting ragdoll parts).
 /// If CCD is on and not teleporting, this will affect objects along the entire swept volume.</param>
 /// <returns>Whether the rotation was successfully set.</returns>
 public bool SetActorLocationAndRotation(FVector newLocation, FQuat newRotation, bool sweep = false, ETeleportType teleport = ETeleportType.None)
 {
     return(Native_AActor.SetActorLocationAndRotationQuat(this.Address, ref newLocation, ref newRotation, sweep, (int)teleport));
 }
Exemple #19
0
 /// <summary>
 /// Set the rotation of the component relative to its parent
 /// </summary>
 /// <param name="newRotation">New rotation of the component relative to its parent</param>
 /// <param name="sweep">Whether we sweep to the destination (currently not supported for rotation).</param>
 /// <param name="teleport">Whether we teleport the physics state (if physics collision is enabled for this object).
 /// If true, physics velocity for this object is unchanged (so ragdoll parts are not affected by change in location).
 /// If false, physics velocity is updated based on the change in position (affecting ragdoll parts).</param>
 public void SetRelativeRotation(FQuat newRotation, bool sweep = false, ETeleportType teleport = ETeleportType.None)
 {
     Native_USceneComponent.SetRelativeRotationQuat(this.Address, ref newRotation, sweep, (int)teleport);
 }
Exemple #20
0
        public void Quat4()
        {
            FQuat fq  = FQuat.Euler(( Fix64 )45, ( Fix64 )(-23), ( Fix64 )(-48.88));
            FQuat fq2 = FQuat.Euler(( Fix64 )23, ( Fix64 )(-78), ( Fix64 )(-132.43f));
            Quat  q   = Quat.Euler(45, -23, -48.88f);
            Quat  q2  = Quat.Euler(23, -78, -132.43f);
            FVec3 fv  = new FVec3(12.5f, 9, 8);
            FVec3 fv2 = new FVec3(1, 0, 0);
            Vec3  v   = new Vec3(12.5f, 9, 8);
            Vec3  v2  = new Vec3(1, 0, 0);

            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            this._output.WriteLine(fq2.ToString());
            this._output.WriteLine(q2.ToString());
            Fix64 fa = FQuat.Angle(fq, fq2);
            float a  = Quat.Angle(q, q2);

            this._output.WriteLine(fa.ToString());
            this._output.WriteLine(a.ToString());
            fq = FQuat.AngleAxis(( Fix64 )(-123.324), fv);
            q  = Quat.AngleAxis(-123.324f, v);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fa = FQuat.Dot(fq, fq2);
            a  = Quat.Dot(q, q2);
            this._output.WriteLine(fa.ToString());
            this._output.WriteLine(a.ToString());
            fq = FQuat.FromToRotation(FVec3.Normalize(fv), fv2);
            q  = Quat.FromToRotation(Vec3.Normalize(v), v2);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fq = FQuat.Lerp(fq, fq2, ( Fix64 )0.66);
            q  = Quat.Lerp(q, q2, 0.66f);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fq = FQuat.Normalize(fq);
            q.Normalize();
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fq.Inverse();
            q = Quat.Inverse(q);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fv = FQuat.Orthogonal(fv);
            v  = Quat.Orthogonal(v);
            this._output.WriteLine(fv.ToString());
            this._output.WriteLine(v.ToString());
            fq = FQuat.Slerp(fq, fq2, ( Fix64 )0.66);
            q  = Quat.Slerp(q, q2, 0.66f);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fq = FQuat.LookRotation(FVec3.Normalize(fv), fv2);
            q  = Quat.LookRotation(Vec3.Normalize(v), v2);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fq.ToAngleAxis(out fa, out fv);
            q.ToAngleAxis(out a, out v);
            this._output.WriteLine(fa.ToString());
            this._output.WriteLine(a.ToString());
            this._output.WriteLine(fv.ToString());
            this._output.WriteLine(v.ToString());
            fq = fq.Conjugate();
            q  = q.Conjugate();
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
            fq.SetLookRotation(FVec3.Normalize(fv), fv2);
            q.SetLookRotation(Vec3.Normalize(v), v2);
            this._output.WriteLine(fq.ToString());
            this._output.WriteLine(q.ToString());
        }
Exemple #21
0
        // DstPos and/or DstQuat will not be changed when KeyPos and/or KeyQuat are empty.
        public void GetBonePosition(float frame, float numFrames, bool loop, ref FVector dstPos, ref FQuat dstQuat)
        {
            // fast case: 1 frame only
            if (KeyTime.Length == 1 || numFrames == 1 || frame == 0)
            {
                if (KeyPos.Length > 0)
                {
                    dstPos = KeyPos[0];
                }
                if (KeyQuat.Length > 0)
                {
                    dstQuat = KeyQuat[0];
                }
                return;
            }

            // data for lerping
            int   posX, rotX; // index of previous frame
            int   posY, rotY; // index of next frame
            float posF, rotF; // fraction between X and Y for lerping

            var numTimeKeys = KeyTime.Length;
            var numPosKeys  = KeyPos.Length;
            var numRotKeys  = KeyQuat.Length;

            if (numTimeKeys > 0)
            {
                // here: KeyPos and KeyQuat sizes either equals to 1 or equals to KeyTime size
                Trace.Assert(numPosKeys <= 1 || numPosKeys == numTimeKeys);
                Trace.Assert(numRotKeys == 1 || numRotKeys == numTimeKeys);

                GetKeyParams(KeyTime, frame, numFrames, loop, out posX, out posY, out posF);
                rotX = posX;
                rotY = posY;
                rotF = posF;

                if (numPosKeys <= 1)
                {
                    posX = posY = 0;
                    posF = 0;
                }
                if (numRotKeys == 1)
                {
                    rotX = rotY = 0;
                    rotF = 0;
                }
            }
            else
            {
                // empty KeyTime array - keys are evenly spaced on a time line
                // note: KeyPos and KeyQuat sizes can be different
                if (KeyPosTime.Length > 0)
                {
                    GetKeyParams(KeyPosTime, frame, numFrames, loop, out posX, out posY, out posF);
                }
                else if (numPosKeys > 1)
                {
                    var position = frame / numFrames * numPosKeys;
                    posX = position.FloorToInt();
                    posF = position - posX;
                    posY = posX + 1;
                    if (posY >= numPosKeys)
                    {
                        if (!loop)
                        {
                            posY = numPosKeys - 1;
                            posF = 0;
                        }
                        else
                        {
                            posY = 0;
                        }
                    }
                }
                else
                {
                    posX = posY = 0;
                    posF = 0;
                }

                if (KeyQuatTime.Length > 0)
                {
                    GetKeyParams(KeyQuatTime, frame, numFrames, loop, out rotX, out rotY, out rotF);
                }
                else if (numRotKeys > 1)
                {
                    var Position = frame / numFrames * numRotKeys;
                    rotX = Position.FloorToInt();
                    rotF = Position - rotX;
                    rotY = rotX + 1;
                    if (rotY >= numRotKeys)
                    {
                        if (!loop)
                        {
                            rotY = numRotKeys - 1;
                            rotF = 0;
                        }
                        else
                        {
                            rotY = 0;
                        }
                    }
                }
                else
                {
                    rotX = rotY = 0;
                    rotF = 0;
                }
            }

            // get position
            if (posF > 0)
            {
                dstPos = MathUtils.Lerp(KeyPos[posX], KeyPos[posY], posF);
            }
            else if (numPosKeys > 0) // do not change DstPos when no keys
            {
                dstPos = KeyPos[posX];
            }
            // get orientation
            if (rotF > 0)
            {
                dstQuat = FQuat.Slerp(KeyQuat[rotX], KeyQuat[rotY], rotF);
            }
            else if (numRotKeys > 0) // do not change DstQuat when no keys
            {
                dstQuat = KeyQuat[rotX];
            }
        }
Exemple #22
0
 public FTransform(EForceInit init = EForceInit.ForceInit)
 {
     Rotation    = new FQuat(0f, 0f, 0f, 1f);
     Translation = new FVector(0f);
     Scale3D     = FVector.OneVector;
 }
Exemple #23
0
 public FTransform(FRotator rotation, FVector translation, FVector scale3D)
 {
     Rotation    = new FQuat(rotation);
     Translation = translation;
     Scale3D     = scale3D;
 }
Exemple #24
0
 public FTransform(FQuat rotation, FVector translation, FVector scale3D)
 {
     Rotation    = rotation;
     Translation = translation;
     Scale3D     = scale3D;
 }