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(); }
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); }
/// <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); }
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); }
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; }
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()); }
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); }
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); } }
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()); }
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()); }
public FQuatRotationMatrix(FQuat q) : base(q, FVector.ZeroVector) { }
/// <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); }
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)); }
public static FMat4 FromRotationAxis(Fix64 angle, FVec3 axis) { FQuat quaternion = FQuat.AngleAxis(angle, axis); return(FromQuaternion(quaternion)); }
/// <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); }
/// <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); }
/// <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)); }
/// <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); }
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()); }
// 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]; } }
public FTransform(EForceInit init = EForceInit.ForceInit) { Rotation = new FQuat(0f, 0f, 0f, 1f); Translation = new FVector(0f); Scale3D = FVector.OneVector; }
public FTransform(FRotator rotation, FVector translation, FVector scale3D) { Rotation = new FQuat(rotation); Translation = translation; Scale3D = scale3D; }
public FTransform(FQuat rotation, FVector translation, FVector scale3D) { Rotation = rotation; Translation = translation; Scale3D = scale3D; }