< Summary

Information
Class: FixedMathSharp.FixedTransform
Assembly: FixedMathSharp
File(s): /home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Matrices/FixedTransform.cs
Line coverage
100%
Covered lines: 243
Uncovered lines: 0
Coverable lines: 243
Total lines: 631
Line coverage: 100%
Branch coverage
100%
Covered branches: 106
Total branches: 106
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%11100%
get_LocalPosition()100%11100%
set_LocalPosition(...)100%11100%
get_LocalRotation()100%11100%
set_LocalRotation(...)100%11100%
get_LocalScale()100%11100%
set_LocalScale(...)100%11100%
get_LocalEulerAngles()100%11100%
set_LocalEulerAngles(...)100%11100%
get_LocalPositionXZ()100%11100%
set_LocalPositionXZ(...)100%11100%
get_LocalRotationXZRadians()100%11100%
set_LocalRotationXZRadians(...)100%11100%
get_LocalScaleXZ()100%11100%
set_LocalScaleXZ(...)100%11100%
get_Parent()100%11100%
get_LocalMatrix()100%11100%
get_LocalToWorldMatrix()100%22100%
TryGetLocalToWorldMatrix(...)100%88100%
get_WorldPosition()100%22100%
get_WorldRotation()100%44100%
get_LossyScale()100%88100%
TryGetLossyScale(...)100%1010100%
get_WorldPositionXZ()100%11100%
get_WorldRotationXZRadians()100%11100%
TryGetWorldToLocalMatrix(...)100%22100%
TransformPoint(...)100%22100%
TryTransformPoint(...)100%22100%
InverseTransformPoint(...)100%22100%
TryInverseTransformPoint(...)100%22100%
TransformPointXZ(...)100%22100%
TryTransformPointXZ(...)100%44100%
InverseTransformPointXZ(...)100%22100%
TryInverseTransformPointXZ(...)100%66100%
SetParentKeepingLocal(...)100%22100%
TrySetParentKeepingWorld(...)100%1212100%
TrySetWorldPosition(...)100%66100%
TrySetWorldPose(...)100%66100%
TryCreateFromLocalMatrix(...)100%22100%
TryGetVerifiedInverse(...)100%1010100%
TryGetPlanarXZMatrix(...)100%44100%
TryGetStrictLocalMatrix(...)100%22100%
ValidateParent(...)100%44100%

File(s)

/home/runner/work/FixedMathSharp/FixedMathSharp/src/FixedMathSharp/Numerics/Matrices/FixedTransform.cs

#LineLine coverage
 1//=======================================================================
 2// FixedTransform.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9
 10namespace FixedMathSharp;
 11
 12/// <summary>
 13/// Provides a mutable deterministic transform snapshot with optional hierarchy composition.
 14/// </summary>
 15/// <remarks>
 16/// This engine-neutral shell stores local components and a parent reference only. It does not
 17/// own children, scene state, synchronization, caches, or dirty propagation.
 18/// </remarks>
 19public class FixedTransform
 20{
 21    private Vector3d _localPosition;
 22    private FixedQuaternion _localRotation;
 23    private Vector3d _localScale;
 24    private FixedTransform? _parent;
 25
 26    /// <summary>
 27    /// Initializes a transform from authoritative 3D local components.
 28    /// </summary>
 1008429    public FixedTransform(
 1008430        Vector3d localPosition,
 1008431        FixedQuaternion localRotation,
 1008432        Vector3d localScale,
 1008433        FixedTransform? parent = null)
 34    {
 1008435        _localPosition = localPosition;
 1008436        _localRotation = localRotation.Normalized;
 1008437        _localScale = localScale;
 1008438        _parent = parent;
 1008439    }
 40
 41    /// <summary>
 42    /// Initializes an X/Z local transform at zero Y position with unit Y scale.
 43    /// </summary>
 44    public FixedTransform(
 45        Vector2d localPositionXZ,
 46        Fixed64 localRotationXZRadians,
 47        Vector2d localScaleXZ,
 48        FixedTransform? parent = null)
 1349        : this(
 1350            localPositionXZ.ToVector3d(Fixed64.Zero),
 1351            FixedQuaternion.FromAxisAngle(Vector3d.Up, -localRotationXZRadians),
 1352            localScaleXZ.ToVector3d(Fixed64.One),
 1353            parent)
 1354    { }
 55
 56    /// <summary>
 57    /// Gets or sets the authoritative local translation.
 58    /// </summary>
 59    public Vector3d LocalPosition
 60    {
 2961        get => _localPosition;
 262        set => _localPosition = value;
 63    }
 64
 65    /// <summary>
 66    /// Gets or sets the authoritative normalized local rotation.
 67    /// </summary>
 68    public FixedQuaternion LocalRotation
 69    {
 3670        get => _localRotation;
 471        set => _localRotation = value.Normalized;
 72    }
 73
 74    /// <summary>
 75    /// Gets or sets the authoritative exact signed local scale.
 76    /// </summary>
 77    public Vector3d LocalScale
 78    {
 2479        get => _localScale;
 280        set => _localScale = value;
 81    }
 82
 83    /// <summary>
 84    /// Gets or sets the local rotation as Euler angles in degrees.
 85    /// </summary>
 86    public Vector3d LocalEulerAngles
 87    {
 188        get => _localRotation.EulerAngles;
 189        set => LocalRotation = FixedQuaternion.FromEulerAnglesInDegrees(value.X, value.Y, value.Z);
 90    }
 91
 92    /// <summary>
 93    /// Gets or sets local X/Z position while preserving local Y.
 94    /// </summary>
 95    public Vector2d LocalPositionXZ
 96    {
 197        get => _localPosition.ToVector2d();
 198        set => _localPosition = value.ToVector3d(_localPosition.Y);
 99    }
 100
 101    /// <summary>
 102    /// Gets or sets local X/Z rotation in radians from planar right toward planar forward.
 103    /// </summary>
 104    /// <remarks>The setter replaces pitch and roll with a pure Y-axis rotation.</remarks>
 105    public Fixed64 LocalRotationXZRadians
 106    {
 107        get
 108        {
 8109            Vector3d localRight = _localRotation.Rotate(Vector3d.Right);
 8110            return FixedMath.Atan2(localRight.Z, localRight.X);
 111        }
 2112        set => LocalRotation = FixedQuaternion.FromAxisAngle(Vector3d.Up, -value);
 113    }
 114
 115    /// <summary>
 116    /// Gets or sets local X/Z scale while preserving local Y.
 117    /// </summary>
 118    public Vector2d LocalScaleXZ
 119    {
 1120        get => _localScale.ToVector2d();
 1121        set => _localScale = value.ToVector3d(_localScale.Y);
 122    }
 123
 124    /// <summary>
 125    /// Gets the optional parent transform.
 126    /// </summary>
 15127    public FixedTransform? Parent => _parent;
 128
 129    /// <summary>
 130    /// Gets the matrix rebuilt from the authoritative local components.
 131    /// </summary>
 28505132    public Fixed4x4 LocalMatrix => Fixed4x4.CreateTransform(_localPosition, _localRotation, _localScale);
 133
 134    /// <summary>
 135    /// Gets the iteratively composed local-to-world matrix.
 136    /// </summary>
 137    /// <remarks>
 138    /// Row-vector order multiplies this local matrix by its parent local matrix and then each
 139    /// ancestor local matrix. Reading is linear in hierarchy depth and allocation-free.
 140    /// </remarks>
 141    public Fixed4x4 LocalToWorldMatrix
 142    {
 143        get
 144        {
 2086145            Fixed4x4 matrix = LocalMatrix;
 2086146            FixedTransform? ancestor = _parent;
 28493147            while (ancestor != null)
 148            {
 26407149                matrix *= ancestor.LocalMatrix;
 26407150                ancestor = ancestor._parent;
 151            }
 152
 2086153            return matrix;
 154        }
 155    }
 156
 157    /// <summary>
 158    /// Attempts to get the iteratively composed local-to-world matrix without intermediate saturation.
 159    /// </summary>
 160    /// <remarks>Failure returns a zero matrix and does not mutate this transform or any ancestor.</remarks>
 161    public bool TryGetLocalToWorldMatrix(out Fixed4x4 matrix)
 162    {
 4391163        if (!TryGetStrictLocalMatrix(out matrix))
 6164            return false;
 165
 4385166        FixedTransform? ancestor = _parent;
 4399167        while (ancestor != null)
 168        {
 17169            if (!ancestor.TryGetStrictLocalMatrix(out Fixed4x4 localMatrix)
 17170                || !Fixed4x4.TryMultiply(matrix, localMatrix, out Fixed4x4 combined))
 171            {
 3172                matrix = Fixed4x4.Zero;
 3173                return false;
 174            }
 175
 14176            matrix = combined;
 14177            ancestor = ancestor._parent;
 178        }
 179
 4382180        return true;
 181    }
 182
 183    /// <summary>
 184    /// Gets world translation from the composed matrix.
 185    /// </summary>
 7186    public Vector3d WorldPosition => _parent == null
 7187        ? _localPosition
 7188        : LocalToWorldMatrix.Translation;
 189
 190    /// <summary>
 191    /// Gets the normalized rotational parent-to-child quaternion chain.
 192    /// </summary>
 193    /// <remarks>
 194    /// This is an orientation chain derived only from stored local quaternions. It is independent
 195    /// of scale, reflections, and any shear in <see cref="LocalToWorldMatrix"/>, so it is not a
 196    /// decomposition of that matrix.
 197    /// </remarks>
 198    public FixedQuaternion WorldRotation
 199    {
 200        get
 201        {
 8202            if (_parent == null)
 3203                return _localRotation;
 204
 5205            FixedQuaternion rotation = _localRotation;
 5206            FixedTransform? ancestor = _parent;
 12207            while (ancestor != null)
 208            {
 7209                rotation = ancestor._localRotation * rotation;
 7210                ancestor = ancestor._parent;
 211            }
 212
 5213            return rotation.Normalized;
 214        }
 215    }
 216
 217    /// <summary>
 218    /// Gets canonical signed lossy scale from the composed matrix.
 219    /// </summary>
 220    /// <remarks>Zero magnitudes are preserved and reflected handedness is canonicalized to negative X.</remarks>
 5221    public Vector3d LossyScale => _parent == null
 5222        && _localScale.X >= Fixed64.Zero
 5223        && _localScale.Y >= Fixed64.Zero
 5224        && _localScale.Z >= Fixed64.Zero
 5225            ? _localScale
 5226            : LocalToWorldMatrix.LossyScale;
 227
 228    /// <summary>
 229    /// Attempts to get canonical signed lossy scale from strict hierarchy composition.
 230    /// </summary>
 231    /// <remarks>Failure returns zero and does not mutate this transform or any ancestor.</remarks>
 232    public bool TryGetLossyScale(out Vector3d scale)
 233    {
 6234        if (_parent == null
 6235            && _localScale.X >= Fixed64.Zero
 6236            && _localScale.Y >= Fixed64.Zero
 6237            && _localScale.Z >= Fixed64.Zero)
 238        {
 1239            scale = _localScale;
 1240            return true;
 241        }
 242
 5243        if (!TryGetLocalToWorldMatrix(out Fixed4x4 matrix))
 244        {
 2245            scale = Vector3d.Zero;
 2246            return false;
 247        }
 248
 3249        return Fixed4x4.TryExtractLossyScale(matrix, out scale);
 250    }
 251
 252    /// <summary>
 253    /// Gets world position projected onto X/Z.
 254    /// </summary>
 2255    public Vector2d WorldPositionXZ => WorldPosition.ToVector2d();
 256
 257    /// <summary>
 258    /// Gets world X/Z rotation in radians from planar right toward planar forward.
 259    /// </summary>
 260    public Fixed64 WorldRotationXZRadians
 261    {
 262        get
 263        {
 1264            Vector3d worldRight = WorldRotation.Rotate(Vector3d.Right);
 1265            return FixedMath.Atan2(worldRight.Z, worldRight.X);
 266        }
 267    }
 268
 269    /// <summary>
 270    /// Attempts to get a verified inverse of the composed local-to-world matrix.
 271    /// </summary>
 272    /// <remarks>
 273    /// The inverse candidate must multiply to identity in both orders within
 274    /// <see cref="FixedMath.CanonicalSinCosErrorBound"/>. Singular, saturated,
 275    /// and unrepresentable candidates return identity and false.
 276    /// </remarks>
 277    public bool TryGetWorldToLocalMatrix(out Fixed4x4 matrix)
 278    {
 1099279        if (!TryGetLocalToWorldMatrix(out Fixed4x4 world))
 280        {
 1281            matrix = Fixed4x4.Identity;
 1282            return false;
 283        }
 284
 1098285        return TryGetVerifiedInverse(world, out matrix);
 286    }
 287
 288    /// <summary>
 289    /// Transforms a point from local space to world space through the complete composed affine hierarchy.
 290    /// </summary>
 291    /// <exception cref="InvalidOperationException">
 292    /// The composed transform or final world-space point is not representable.
 293    /// </exception>
 294    public Vector3d TransformPoint(Vector3d point)
 295    {
 2296        if (!TryTransformPoint(point, out Vector3d result))
 1297            throw new InvalidOperationException(
 1298                "The composed transform or final world-space point is not representable.");
 299
 1300        return result;
 301    }
 302
 303    /// <summary>
 304    /// Attempts to transform a point from local space to world space through the complete composed affine hierarchy.
 305    /// </summary>
 306    public bool TryTransformPoint(Vector3d point, out Vector3d result)
 307    {
 1093308        if (!TryGetLocalToWorldMatrix(out Fixed4x4 matrix))
 309        {
 2310            result = default;
 2311            return false;
 312        }
 313
 1091314        return Fixed4x4.TryTransformAffinePoint(matrix, point, out result);
 315    }
 316
 317    /// <summary>
 318    /// Transforms a point from world space to local space through the complete composed affine hierarchy.
 319    /// </summary>
 320    /// <exception cref="InvalidOperationException">
 321    /// The composed transform is singular or unrepresentable, or the final local-space point is not representable.
 322    /// </exception>
 323    public Vector3d InverseTransformPoint(Vector3d point)
 324    {
 2325        if (!TryInverseTransformPoint(point, out Vector3d result))
 1326            throw new InvalidOperationException(
 1327                "The composed transform is singular or unrepresentable, or the final local-space point is not representa
 328
 1329        return result;
 330    }
 331
 332    /// <summary>
 333    /// Attempts to transform a point from world space to local space through the complete composed affine hierarchy.
 334    /// </summary>
 335    public bool TryInverseTransformPoint(Vector3d point, out Vector3d result)
 336    {
 1092337        if (!TryGetWorldToLocalMatrix(out Fixed4x4 matrix))
 338        {
 2339            result = default;
 2340            return false;
 341        }
 342
 1090343        return Fixed4x4.TryTransformAffinePoint(matrix, point, out result);
 344    }
 345
 346    /// <summary>
 347    /// Transforms a point from local X/Z space to world X/Z space through a plane-preserving affine hierarchy.
 348    /// </summary>
 349    /// <exception cref="InvalidOperationException">
 350    /// The hierarchy couples X/Z with Y, or the composed transform or final world-space point is not representable.
 351    /// </exception>
 352    public Vector2d TransformPointXZ(Vector2d point)
 353    {
 2354        if (!TryTransformPointXZ(point, out Vector2d result))
 1355            throw new InvalidOperationException(
 1356                "The hierarchy must preserve the X/Z plane and produce a representable world-space point.");
 357
 1358        return result;
 359    }
 360
 361    /// <summary>
 362    /// Attempts to transform a point from local X/Z space to world X/Z space through a plane-preserving affine hierarch
 363    /// </summary>
 364    public bool TryTransformPointXZ(Vector2d point, out Vector2d result)
 365    {
 1094366        if (!TryGetPlanarXZMatrix(out Fixed4x4 matrix)
 1094367            || !Fixed4x4.TryTransformAffinePoint(
 1094368                matrix,
 1094369                point.ToVector3d(Fixed64.Zero),
 1094370                out Vector3d transformed))
 371        {
 4372            result = default;
 4373            return false;
 374        }
 375
 1090376        result = transformed.ToVector2d();
 1090377        return true;
 378    }
 379
 380    /// <summary>
 381    /// Transforms a point from world X/Z space to local X/Z space through a plane-preserving affine hierarchy.
 382    /// </summary>
 383    /// <exception cref="InvalidOperationException">
 384    /// The hierarchy couples X/Z with Y, is singular or unrepresentable, or the final local-space point is not represen
 385    /// </exception>
 386    public Vector2d InverseTransformPointXZ(Vector2d point)
 387    {
 2388        if (!TryInverseTransformPointXZ(point, out Vector2d result))
 1389            throw new InvalidOperationException(
 1390                "The hierarchy must preserve an invertible X/Z plane and produce a representable local-space point.");
 391
 1392        return result;
 393    }
 394
 395    /// <summary>
 396    /// Attempts to transform a point from world X/Z space to local X/Z space through a plane-preserving affine hierarch
 397    /// </summary>
 398    public bool TryInverseTransformPointXZ(Vector2d point, out Vector2d result)
 399    {
 1095400        if (!TryGetPlanarXZMatrix(out Fixed4x4 matrix)
 1095401            || !TryGetVerifiedInverse(matrix, out Fixed4x4 inverse)
 1095402            || !Fixed4x4.TryTransformAffinePoint(
 1095403                inverse,
 1095404                point.ToVector3d(Fixed64.Zero),
 1095405                out Vector3d transformed))
 406        {
 5407            result = default;
 5408            return false;
 409        }
 410
 1090411        result = transformed.ToVector2d();
 1090412        return true;
 413    }
 414
 415    /// <summary>
 416    /// Changes the parent without changing any local component.
 417    /// </summary>
 418    /// <exception cref="ArgumentException">The proposed parent would create a cycle.</exception>
 419    public void SetParentKeepingLocal(FixedTransform? parent)
 420    {
 5421        if (ReferenceEquals(_parent, parent))
 1422            return;
 423
 4424        ValidateParent(parent);
 2425        _parent = parent;
 2426    }
 427
 428    /// <summary>
 429    /// Attempts to change the parent while preserving the complete world matrix.
 430    /// </summary>
 431    /// <remarks>Failure leaves the parent and every local component unchanged.</remarks>
 432    /// <exception cref="ArgumentException">The proposed parent would create a cycle.</exception>
 433    public bool TrySetParentKeepingWorld(FixedTransform? parent)
 434    {
 7435        if (ReferenceEquals(_parent, parent))
 1436            return true;
 437
 6438        ValidateParent(parent);
 5439        Fixed4x4 world = LocalToWorldMatrix;
 5440        Fixed4x4 parentWorld = parent?.LocalToWorldMatrix ?? Fixed4x4.Identity;
 441        Fixed4x4 localMatrix;
 5442        if (parent == null)
 443        {
 1444            localMatrix = world;
 445        }
 446        else
 447        {
 4448            if (!TryGetVerifiedInverse(parentWorld, out Fixed4x4 parentInverse))
 1449                return false;
 450
 3451            localMatrix = world * parentInverse;
 452        }
 453
 4454        if (!Fixed4x4.Decompose(
 4455            localMatrix,
 4456            out Vector3d localPosition,
 4457            out FixedQuaternion localRotation,
 4458            out Vector3d localScale))
 459        {
 1460            return false;
 461        }
 462
 3463        Fixed4x4 recomposedWorld = Fixed4x4.CreateTransform(localPosition, localRotation, localScale) * parentWorld;
 3464        if (!recomposedWorld.FuzzyEqualAbsolute(world, Fixed64.Epsilon))
 1465            return false;
 466
 2467        _parent = parent;
 2468        _localPosition = localPosition;
 2469        _localRotation = localRotation;
 2470        _localScale = localScale;
 2471        return true;
 472    }
 473
 474    /// <summary>
 475    /// Attempts to set world position through the verified parent inverse.
 476    /// </summary>
 477    /// <remarks>Failure leaves local position unchanged.</remarks>
 478    public bool TrySetWorldPosition(Vector3d position)
 479    {
 4480        if (_parent == null)
 481        {
 1482            _localPosition = position;
 1483            return true;
 484        }
 485
 3486        Fixed4x4 parentWorld = _parent.LocalToWorldMatrix;
 3487        if (!TryGetVerifiedInverse(parentWorld, out Fixed4x4 parentInverse))
 1488            return false;
 489
 2490        Vector3d localPosition = Fixed4x4.TransformPoint(parentInverse, position);
 2491        if (!Fixed4x4.TransformPoint(parentWorld, localPosition).FuzzyEqualAbsolute(position, Fixed64.Epsilon))
 1492            return false;
 493
 1494        _localPosition = localPosition;
 1495        return true;
 496    }
 497
 498    /// <summary>
 499    /// Attempts to set world position and normalized world rotation atomically.
 500    /// </summary>
 501    /// <remarks>
 502    /// Relative rotation is derived from the parent's stored rotational hierarchy, independent
 503    /// of scale and shear. Failure leaves both local position and local rotation unchanged.
 504    /// </remarks>
 505    public bool TrySetWorldPose(Vector3d position, FixedQuaternion rotation)
 506    {
 4507        FixedQuaternion normalizedRotation = rotation.Normalized;
 4508        if (_parent == null)
 509        {
 1510            _localPosition = position;
 1511            _localRotation = normalizedRotation;
 1512            return true;
 513        }
 514
 3515        Fixed4x4 parentWorld = _parent.LocalToWorldMatrix;
 3516        if (!TryGetVerifiedInverse(parentWorld, out Fixed4x4 parentInverse))
 1517            return false;
 518
 2519        Vector3d localPosition = Fixed4x4.TransformPoint(parentInverse, position);
 2520        if (!Fixed4x4.TransformPoint(parentWorld, localPosition).FuzzyEqualAbsolute(position, Fixed64.Epsilon))
 1521            return false;
 522
 1523        FixedQuaternion parentWorldRotation = _parent.WorldRotation;
 1524        FixedQuaternion localRotation = (parentWorldRotation.Inverse() * normalizedRotation).Normalized;
 525
 1526        _localPosition = localPosition;
 1527        _localRotation = localRotation;
 1528        return true;
 529    }
 530
 531    /// <summary>
 532    /// Attempts to create a transform from a strict, nonsingular local TRS matrix.
 533    /// </summary>
 534    /// <remarks>Perspective, shear, singular, and non-round-trippable inputs return null and false.</remarks>
 535    public static bool TryCreateFromLocalMatrix(
 536        Fixed4x4 localMatrix,
 537        out FixedTransform? transform,
 538        FixedTransform? parent = null)
 539    {
 4540        if (!Fixed4x4.Decompose(
 4541            localMatrix,
 4542            out Vector3d localPosition,
 4543            out FixedQuaternion localRotation,
 4544            out Vector3d localScale))
 545        {
 3546            transform = null;
 3547            return false;
 548        }
 549
 1550        transform = new FixedTransform(localPosition, localRotation, localScale, parent);
 1551        return true;
 552    }
 553
 554    private static bool TryGetVerifiedInverse(Fixed4x4 world, out Fixed4x4 inverse)
 555    {
 2200556        if (Fixed4x4.Invert(world, out Fixed4x4 candidate)
 2200557            && Fixed4x4.TryMultiply(world, candidate, out Fixed4x4 worldRoundTrip)
 2200558            && Fixed4x4.TryMultiply(candidate, world, out Fixed4x4 localRoundTrip)
 2200559            && worldRoundTrip.FuzzyEqualAbsolute(
 2200560                Fixed4x4.Identity,
 2200561                FixedMath.CanonicalSinCosErrorBound)
 2200562            && localRoundTrip.FuzzyEqualAbsolute(
 2200563                Fixed4x4.Identity,
 2200564                FixedMath.CanonicalSinCosErrorBound))
 565        {
 2193566            inverse = candidate;
 2193567            return true;
 568        }
 569
 7570        inverse = Fixed4x4.Identity;
 7571        return false;
 572    }
 573
 574    private bool TryGetPlanarXZMatrix(out Fixed4x4 matrix)
 575    {
 2189576        if (!TryGetLocalToWorldMatrix(out Fixed4x4 world)
 2189577            || ((world.M12 != Fixed64.Zero)
 2189578                | (world.M21 != Fixed64.Zero)
 2189579                | (world.M23 != Fixed64.Zero)
 2189580                | (world.M32 != Fixed64.Zero)))
 581        {
 7582            matrix = Fixed4x4.Zero;
 7583            return false;
 584        }
 585
 2182586        matrix = new Fixed4x4(
 2182587            world.M11, Fixed64.Zero, world.M13, Fixed64.Zero,
 2182588            Fixed64.Zero, Fixed64.One, Fixed64.Zero, Fixed64.Zero,
 2182589            world.M31, Fixed64.Zero, world.M33, Fixed64.Zero,
 2182590            world.M41, Fixed64.Zero, world.M43, Fixed64.One);
 2182591        return true;
 592    }
 593
 594    private bool TryGetStrictLocalMatrix(out Fixed4x4 matrix)
 595    {
 4408596        Fixed3x3 rotation = _localRotation.ToMatrix3x3();
 4408597        bool representable = Fixed64.TryMultiplyAdd(rotation.M11, _localScale.X, Fixed64.Zero, out Fixed64 m11)
 4408598            & Fixed64.TryMultiplyAdd(rotation.M12, _localScale.X, Fixed64.Zero, out Fixed64 m12)
 4408599            & Fixed64.TryMultiplyAdd(rotation.M13, _localScale.X, Fixed64.Zero, out Fixed64 m13)
 4408600            & Fixed64.TryMultiplyAdd(rotation.M21, _localScale.Y, Fixed64.Zero, out Fixed64 m21)
 4408601            & Fixed64.TryMultiplyAdd(rotation.M22, _localScale.Y, Fixed64.Zero, out Fixed64 m22)
 4408602            & Fixed64.TryMultiplyAdd(rotation.M23, _localScale.Y, Fixed64.Zero, out Fixed64 m23)
 4408603            & Fixed64.TryMultiplyAdd(rotation.M31, _localScale.Z, Fixed64.Zero, out Fixed64 m31)
 4408604            & Fixed64.TryMultiplyAdd(rotation.M32, _localScale.Z, Fixed64.Zero, out Fixed64 m32)
 4408605            & Fixed64.TryMultiplyAdd(rotation.M33, _localScale.Z, Fixed64.Zero, out Fixed64 m33);
 4408606        if (!representable)
 607        {
 7608            matrix = Fixed4x4.Zero;
 7609            return false;
 610        }
 611
 4401612        matrix = new Fixed4x4(
 4401613            m11, m12, m13, Fixed64.Zero,
 4401614            m21, m22, m23, Fixed64.Zero,
 4401615            m31, m32, m33, Fixed64.Zero,
 4401616            _localPosition.X, _localPosition.Y, _localPosition.Z, Fixed64.One);
 4401617        return true;
 618    }
 619
 620    private void ValidateParent(FixedTransform? parent)
 621    {
 10622        FixedTransform? ancestor = parent;
 19623        while (ancestor != null)
 624        {
 12625            if (ReferenceEquals(ancestor, this))
 3626                throw new ArgumentException("Parent assignment would create a transform cycle.", nameof(parent));
 627
 9628            ancestor = ancestor._parent;
 629        }
 7630    }
 631}

Methods/Properties

.ctor(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,FixedMathSharp.FixedTransform)
.ctor(FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.FixedTransform)
get_LocalPosition()
set_LocalPosition(FixedMathSharp.Vector3d)
get_LocalRotation()
set_LocalRotation(FixedMathSharp.FixedQuaternion)
get_LocalScale()
set_LocalScale(FixedMathSharp.Vector3d)
get_LocalEulerAngles()
set_LocalEulerAngles(FixedMathSharp.Vector3d)
get_LocalPositionXZ()
set_LocalPositionXZ(FixedMathSharp.Vector2d)
get_LocalRotationXZRadians()
set_LocalRotationXZRadians(FixedMathSharp.Fixed64)
get_LocalScaleXZ()
set_LocalScaleXZ(FixedMathSharp.Vector2d)
get_Parent()
get_LocalMatrix()
get_LocalToWorldMatrix()
TryGetLocalToWorldMatrix(FixedMathSharp.Fixed4x4&)
get_WorldPosition()
get_WorldRotation()
get_LossyScale()
TryGetLossyScale(FixedMathSharp.Vector3d&)
get_WorldPositionXZ()
get_WorldRotationXZRadians()
TryGetWorldToLocalMatrix(FixedMathSharp.Fixed4x4&)
TransformPoint(FixedMathSharp.Vector3d)
TryTransformPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
InverseTransformPoint(FixedMathSharp.Vector3d)
TryInverseTransformPoint(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TransformPointXZ(FixedMathSharp.Vector2d)
TryTransformPointXZ(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
InverseTransformPointXZ(FixedMathSharp.Vector2d)
TryInverseTransformPointXZ(FixedMathSharp.Vector2d,FixedMathSharp.Vector2d&)
SetParentKeepingLocal(FixedMathSharp.FixedTransform)
TrySetParentKeepingWorld(FixedMathSharp.FixedTransform)
TrySetWorldPosition(FixedMathSharp.Vector3d)
TrySetWorldPose(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
TryCreateFromLocalMatrix(FixedMathSharp.Fixed4x4,FixedMathSharp.FixedTransform&,FixedMathSharp.FixedTransform)
TryGetVerifiedInverse(FixedMathSharp.Fixed4x4,FixedMathSharp.Fixed4x4&)
TryGetPlanarXZMatrix(FixedMathSharp.Fixed4x4&)
TryGetStrictLocalMatrix(FixedMathSharp.Fixed4x4&)
ValidateParent(FixedMathSharp.FixedTransform)