Exemple #1
0
        public static Matrix3D GetTotalTransform(Camera cam, double aspectRatio)
        {
            Matrix3D matx = Matrix3D.Identity;

            if (cam == null)
            {
                matx = ZeroMatrix;
            }

            else
            {
                if (cam.Transform != null)
                {
                    Matrix3D matxCameraTransform = cam.Transform.Value;

                    if (!matxCameraTransform.HasInverse)
                    {
                        matx = ZeroMatrix;
                    }
                    else
                    {
                        matxCameraTransform.Invert();
                        matx.Append(matxCameraTransform);
                    }
                }

                matx.Append(CameraInfo.GetViewMatrix(cam));
                matx.Append(CameraInfo.GetProjectionMatrix(cam, aspectRatio));
            }
            return(matx);
        }
Exemple #2
0
        /// <summary>
        ///     Computes the transform from the inner space of the given
        ///     Visual3D to the 2D space of the Viewport3DVisual which
        ///     contains it.
        ///
        ///     The result will contain the transform of the given visual.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="success"></param>
        /// <returns></returns>
        public static Matrix3D TryTransformTo2DAncestor(DependencyObject visual, out Viewport3DVisual viewport, out bool success)
        {
            success = false;
            Matrix3D to2D = Matrix3D.Identity;

            viewport = null;

            if (!(visual is Visual3D))
            {
                throw new ArgumentException("Must be of type Visual3D.", "visual");
            }

            while (visual != null)
            {
                if (!(visual is ModelVisual3D))
                {
                    break;
                }

                Transform3D transform = (Transform3D)visual.GetValue(ModelVisual3D.TransformProperty);

                if (transform != null)
                {
                    to2D.Append(transform.Value);
                }

                visual = VisualTreeHelper.GetParent(visual);
            }

            viewport = visual as Viewport3DVisual;

            if (viewport == null)
            {
                if (visual != null)
                {
                    // In WPF 3D v1 the only possible configuration is a chain of
                    // ModelVisual3Ds leading up to a Viewport3DVisual.

                    throw new ApplicationException(
                              String.Format("Unsupported type: '{0}'.  Expected tree of ModelVisual3Ds leading up to a Viewport3DVisual.",
                                            visual.GetType().FullName));
                }

                return(ZeroMatrix);
            }

            success = true;
            to2D.Append(MathUtils.TryWorldToViewportTransform(viewport, out success));

            if (!success)
            {
                return(ZeroMatrix);
            }

            return(to2D);
        }
Exemple #3
0
        /// <summary>
        ///     Computes the transform from world space to the Viewport3DVisual's
        ///     inner 2D space.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        public static Matrix3D TryWorldToViewportTransform(Viewport3DVisual visual, out bool success)
        {
            Matrix3D result = TryWorldToCameraTransform(visual, out success);

            if (success)
            {
                result.Append(GetProjectionMatrix(visual.Camera, Math2D.GetAspectRatio(visual.Viewport.Size)));
                result.Append(GetHomogeneousToViewportTransform(visual.Viewport));
                success = true;
            }

            return(result);
        }
        public static double GetRotationXZ(this Matrix3D matrix, double rotationZ)
        {
            // back off z rotation
            Matrix3D matrix2 = new Matrix3D();

            matrix2.Append(matrix);
            matrix2 = matrix2.RotateXYZ(new Vector3D(0.0, 0.0, rotationZ * -1.0));

            Vector3D localX = matrix2.Transform(new Vector3D(1, 0, 0));
            Vector3D localY = matrix2.Transform(new Vector3D(0, 1, 0));

            // rotation about the X axis
            localY.X = 0.0;
            double angle     = Vector3D.AngleBetween(localY, new Vector3D(0, 1, 0));
            double rotationX = localX.Z > 0 ? angle * -1.0 : angle;

            if (Abs(rotationX - 180.0) > 0.01 && Abs(localY.Z) < 0.0001)
            {
                rotationX = 0.0;
            }

            if (Abs(localY.Y + 1.0) < 0.01)
            {
                rotationX = 0.0;
            }

            return(rotationX);
        }
        public static Matrix3D GetTotalTransform(Viewport3D viewport)
        {
            Matrix3D matx = GetCameraTransform(viewport);

            matx.Append(GetViewportTransform(viewport));
            return(matx);
        }
Exemple #6
0
        public void OnKeyDown(KeyEventArgs args)
        {
            var f          = 1.0 / ScaleFactor;
            var viewMatrix = new Matrix3D();

            viewMatrix.Append(_viewMatrix);

            switch (args.Key)
            {
            case Key.Home:
                viewMatrix = Matrix3D.Identity;
                break;

            case Key.OemPlus:
                viewMatrix.Scale(new Vector3D(f, f, f));
                break;

            case Key.OemMinus:
                viewMatrix.Scale(new Vector3D(f, f, f));
                break;

            default:
                return;
            }

            _viewMatrix = viewMatrix;
        }
Exemple #7
0
        public void OnMouseMove(Point pt, System.Windows.Controls.Viewport3D viewPort)
        {
            if (_mouseDown)
            {
                var viewMatrix = new Matrix3D();
                var width      = viewPort.ActualWidth;
                var height     = viewPort.ActualHeight;
                viewMatrix.Append(_viewMatrix);

                if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
                {
                }
                else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
                {
                    var shiftX = 2 * (pt.X - _movePoint.X) / (width);
                    var shiftY = -2 * (pt.Y - _movePoint.Y) / (width);

                    viewMatrix.Translate(new Vector3D(shiftX, shiftY, 0));
                    _movePoint = pt;
                }
                else
                {
                    var aY = 180 * (pt.X - _movePoint.X) / width;
                    var aX = 180 * (pt.Y - _movePoint.Y) / height;

                    viewMatrix.Rotate(new Quaternion(new Vector3D(1, 0, 0), aX));
                    viewMatrix.Rotate(new Quaternion(new Vector3D(0, 1, 0), aY));
                    _movePoint = pt;
                }

                _viewMatrix = viewMatrix;
            }
        }
Exemple #8
0
        public static Matrix3D GetTotalTransformViewport3DVisual(Viewport3DVisual vis)
        {
            Matrix3D matx = GetCameraTransform(vis);

            matx.Append(GetViewportTransform(vis));
            return(matx);
        }
Exemple #9
0
        public static void Move(Vector3D direction, Vector3D rotation)
        {
            Matrix3D matrix = Matrix3D.Identity;

            // translation
            if (direction.X != 0)
            {
                matrix = Matrix3D.Multiply(matrix, MoveRight(direction.X));
            }

            if (direction.Y != 0)
            {
                matrix = Matrix3D.Multiply(matrix, MoveForwards(direction.Y));
            }

            // rotation
            if (rotation.X != 0)
            {
                matrix = Matrix3D.Multiply(matrix, Pitch(rotation.X));
            }

            if (rotation.Y != 0)
            {
                matrix = Matrix3D.Multiply(matrix, Jaw(rotation.Y));
            }

            if (rotation.Z != 0)
            {
                matrix = Matrix3D.Multiply(matrix, Roll(rotation.Z));
            }

            OnMoving(matrix);
            Position.Append(matrix);
        }
Exemple #10
0
        /// <summary>
        ///     Computes the transform from world space to camera space
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        public static Matrix3D TryWorldToCameraTransform(Viewport3DVisual visual, out bool success)
        {
            success = false;

            if (visual == null)
            {
                return(ZeroMatrix);
            }


            Matrix3D result = Matrix3D.Identity;

            Camera camera = visual.Camera;

            if (camera == null)
            {
                return(ZeroMatrix);
            }

            Rect viewport = visual.Viewport;

            if (viewport == Rect.Empty)
            {
                return(ZeroMatrix);
            }

            Transform3D cameraTransform = camera.Transform;

            if (cameraTransform != null)
            {
                Matrix3D m = cameraTransform.Value;

                if (!m.HasInverse)
                {
                    return(ZeroMatrix);
                }

                m.Invert();
                result.Append(m);
            }

            result.Append(GetViewMatrix(camera));

            success = true;
            return(result);
        }
Exemple #11
0
        public static Matrix3D BodyToWorldMatrix(Body body, Point3D position, Vector3D direction)
        {
            Matrix3D result = Math3D.CreateZDirectionMatrix(position, direction);

            result.Append(body.Transform.Value);

            return(result);
        }
Exemple #12
0
        /// <summary>
        ///     Converts the given point or ray hit test result into a PointHitTestResult.
        ///     In the case of a RayHitTestResult this is done by walking up the
        ///     transforming the 3D intersection into the coordinate space of the
        ///     Viewport3DVisual which contains the Visual3D subtree.
        /// </summary>
        internal static PointHitTestResult AsNearestPointHitTestResult(HitTestResult result)
        {
            if (result == null)
            {
                return(null);
            }

            PointHitTestResult resultAsPointHitTestResult = result as PointHitTestResult;

            if (resultAsPointHitTestResult != null)
            {
                return(resultAsPointHitTestResult);
            }

            RayHitTestResult resultAsRayHitTestResult = result as RayHitTestResult;

            if (resultAsRayHitTestResult != null)
            {
                Visual3D current        = (Visual3D)resultAsRayHitTestResult.VisualHit;
                Matrix3D worldTransform = Matrix3D.Identity;

                while (true)
                {
                    if (current.Transform != null)
                    {
                        worldTransform.Append(current.Transform.Value);
                    }

                    Visual3D parent3D = current.InternalVisualParent as Visual3D;

                    if (parent3D == null)
                    {
                        break;
                    }

                    current = parent3D;
                }

                Viewport3DVisual viewport = current.InternalVisualParent as Viewport3DVisual;

                if (viewport != null)
                {
                    Point4D worldPoint    = ((Point4D)resultAsRayHitTestResult.PointHit) * worldTransform;
                    Point   viewportPoint = viewport.WorldToViewport(worldPoint);

                    return(new PointHitTestResult(viewport, viewportPoint));
                }

                Debug.Fail("How did a ray hit a Visual3D not parented to a Viewport3DVisual?");

                return(null);
            }

            Debug.Fail(String.Format("Unhandled HitTestResult type '{0}'", result.GetType().Name));

            return(null);
        }
Exemple #13
0
        /// <summary>
        /// Gets the object space to world space transformation for the given DependencyObject
        /// </summary>
        /// <param name="visual">The visual whose world space transform should be found</param>
        /// <param name="viewport">The Viewport3DVisual the Visual is contained within</param>
        /// <returns>The world space transformation</returns>
        private static Matrix3D GetWorldTransformationMatrix(DependencyObject visual, out Viewport3DVisual viewport)
        {
            Matrix3D worldTransform = Matrix3D.Identity;

            viewport = null;



            if (!(visual is Visual3D))
            {
                throw new ArgumentException("Must be of type Visual3D.", "visual");
            }

            while (visual != null)
            {
                Viewport3DVisual test;
                test = visual as Viewport3DVisual;
                if (test != null)
                {
                    break;
                }


                //if (!(visual is ModelVisual3D))
                //{
                //    break;
                //}

                Transform3D transform = (Transform3D)visual.GetValue(ModelVisual3D.TransformProperty);

                if (transform != null)
                {
                    worldTransform.Append(transform.Value);
                }

                visual = VisualTreeHelper.GetParent(visual);
            }

            viewport = visual as Viewport3DVisual;

            if (viewport == null)
            {
                if (visual != null)
                {
                    // In WPF 3D v1 the only possible configuration is a chain of
                    // ModelVisual3Ds leading up to a Viewport3DVisual.

                    throw new ApplicationException(
                              String.Format("Unsupported type: '{0}'.  Expected tree of ModelVisual3Ds leading up to a Viewport3DVisual.",
                                            visual.GetType().FullName));
                }

                return(ZeroMatrix);
            }

            return(worldTransform);
        }
Exemple #14
0
        public static Matrix3D GetTransformToViewport(Visual3D visual)
        {
            Viewport3DVisual viewport;
            Matrix3D         to2D = GetTransformToWorld(visual, out viewport);

            to2D.Append(GetWorldToViewportTransform(viewport));

            return(to2D);
        }
Exemple #15
0
        public static Matrix3D BodyToBodyMatrix(Body fromBody, Body toBody)
        {
            Matrix3D result = toBody.Transform.Value;

            result.Invert();
            result.Append(fromBody.Transform.Value);

            return(result);
        }
Exemple #16
0
        /// <summary>
        ///     Computes the transform from world space to the Viewport3DVisual's
        ///     inner 2D space.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        public static Matrix3D TryWorldToViewportTransform(Viewport3DVisual visual, out bool success)
        {
            success = false;
            if (visual.Viewport.Width == 0 || visual.Viewport.Height == 0)
            {
                return(ZeroMatrix);
            }

            Matrix3D result = TryWorldToCameraTransform(visual, out success);

            if (success)
            {
                result.Append(GetProjectionMatrix(visual.Camera, GetAspectRatio(visual.Viewport.Size)));
                result.Append(GetHomogeneousToViewportTransform(visual.Viewport));
            }

            return(result);
        }
Exemple #17
0
        /// <summary>
        /// Maps the Point in 3D to point in 2D.
        /// </summary>
        /// <param name="point">The 3D point.</param>
        /// <returns></returns>
        private Point Point3DtoPoint2D(Point3D point)
        {
            Matrix3D matrix = ClothingManager.Instance.CameraTransform;

            matrix.Append(ClothingManager.Instance.ViewportTransform);

            Point3D pointTransformed = matrix.Transform(point);

            return(new Point(pointTransformed.X, pointTransformed.Y));
        }
        ///GetCameraTransform - obtener el objeto
        // retorna: Matriz que representa la cameraTransform

        public Matrix3D GetCameraTransform()
        {
            Matrix3D matx = Matrix3D.Identity;

            if (Camera.Transform != null)
            {
                Matrix3D matxCameraTransform = Camera.Transform.Value;

                if (!matxCameraTransform.HasInverse)
                {
                    return(_zeroMatrix);
                }
                matxCameraTransform.Invert();
                matx.Append(matxCameraTransform);
            }

            matx.Append(GetViewMatrix());
            matx.Append(GetProjectionMatrix());
            return(matx);
        }
Exemple #19
0
        /// <summary>
        ///     Computes the transform from world space to the Viewport3DVisual's
        ///     inner 2D space.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        public static Matrix3D TryWorldToViewportTransform(Viewport3DVisual visual, out bool success)
        {
            success = false;
            Matrix3D result = Matrix3D.Identity;

            Camera camera = visual.Camera;

            if (camera == null)
            {
                return(ZeroMatrix);
            }

            Rect viewport = visual.Viewport;

            if (viewport == Rect.Empty)
            {
                return(ZeroMatrix);
            }

            Transform3D cameraTransform = camera.Transform;

            if (cameraTransform != null)
            {
                Matrix3D m = cameraTransform.Value;

                if (!m.HasInverse)
                {
                    return(ZeroMatrix);
                }

                m.Invert();
                result.Append(m);
            }

            result.Append(GetViewMatrix(camera));
            result.Append(GetProjectionMatrix(camera, MathUtils.GetAspectRatio(viewport.Size)));
            result.Append(GetHomogeneousToViewportTransform(viewport));

            success = true;
            return(result);
        }
Exemple #20
0
        /// <summary>
        /// builds & return the transformation from the root bone to this bone.
        /// </summary>
        public Matrix3D GetRootTransform()
        {
            Matrix3D transform = Matrix3D.Identity;
            var      current   = this;

            do
            {
                transform.Append(current.LocalTransform);
                current = current.Parent;
            } while (current != null);

            return(transform);
        }
Exemple #21
0
        /// <summary>
        ///     Computes the transform from the inner space of the given
        ///     Visual3D to the camera coordinate space
        ///
        ///     The result will contain the transform of the given visual.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="success"></param>
        /// <returns></returns>
        public static Matrix3D TryTransformToCameraSpace(DependencyObject visual, out Viewport3DVisual viewport, out bool success)
        {
            Matrix3D toViewSpace = GetWorldTransformationMatrix(visual, out viewport);

            toViewSpace.Append(MUtils.TryWorldToCameraTransform(viewport, out success));

            if (!success)
            {
                return(ZeroMatrix);
            }

            return(toViewSpace);
        }
Exemple #22
0
        /// <summary>
        ///     Computes the transform from the inner space of the given
        ///     Visual3D to the 2D space of the Viewport3DVisual which
        ///     contains it.
        ///
        ///     The result will contain the transform of the given visual.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="success"></param>
        /// <returns></returns>
        public static Matrix3D TryTransformTo2DAncestor(DependencyObject visual, out Viewport3DVisual viewport, out bool success)
        {
            Matrix3D to2D = GetWorldTransformationMatrix(visual, out viewport);

            to2D.Append(MUtils.TryWorldToViewportTransform(viewport, out success));

            if (!success)
            {
                return(ZeroMatrix);
            }

            return(to2D);
        }
        // Return a matrix that combines the view, projection, and viewport transformations.
        public static Matrix3D GetWorldToViewportMatrix(Viewport3DVisual visual)
        {
            Camera   camera = visual.Camera;
            Rect     rect   = visual.Viewport;
            Matrix3D result = Matrix3D.Identity;

            // If the camera has a transform, add its inverse to the result.
            Transform3D transform = camera.Transform;

            if ((transform != null) && (!transform.Value.IsIdentity))
            {
                Matrix3D matrix = transform.Value;
                matrix.Invert();
                result.Append(matrix);
            }

            // Add the view, projection, and viewport transformations.
            result.Append(GetViewMatrix(camera));
            result.Append(GetProjectionMatrix(camera, rect.Width / rect.Height));
            result.Append(GetViewportMatrix(rect));

            return(result);
        }
Exemple #24
0
        public static Matrix3D GetTotalTransformModelVisual3D(ModelVisual3D mv3d)
        {
            Matrix3D         matx = Matrix3D.Identity;
            DependencyObject obj  = mv3d;

            while (!(obj is Viewport3DVisual))
            {
                // This occurs when the visual is parent-less.
                if (obj == null)
                {
                    return(ZeroMatrix);
                }

                else if (obj is ModelVisual3D)
                {
                    if ((obj as ModelVisual3D).Transform != null)
                    {
                        matx.Append((obj as ModelVisual3D).Transform.Value);
                    }
                }

                else
                {
                    throw new ApplicationException("didn't end in Viewport3DVisual");
                }

                obj = VisualTreeHelper.GetParent(obj);
            }

            // At this point, we know obj is Viewport3DVisual
            Viewport3DVisual vis          = obj as Viewport3DVisual;
            Matrix3D         matxViewport = GetTotalTransformViewport3DVisual(vis);

            matx.Append(matxViewport);

            return(matx);
        }
Exemple #25
0
        /// <summary>
        ///     Computes the transform from the inner space of the given
        ///     Visual3D to the 2D space of the Viewport3DVisual which
        ///     contains it.
        ///
        ///     The result will contain the transform of the given visual.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="success"></param>
        /// <returns></returns>
        public static Matrix3D TryTransformTo2DAncestor(DependencyObject visual, out Viewport3DVisual viewport, out bool success)
        {
            Matrix3D to2D = GetWorldTransformationMatrix(visual, out viewport);

            if (viewport == null)
            {
                success = false;
                return(default(Matrix3D));
            }

            to2D.Append(TryWorldToViewportTransform(viewport, out success));

            if (!success)
            {
                return(ZeroMatrix);
            }

            return(to2D);
        }
Exemple #26
0
        public static bool ToViewportTransform(DependencyObject visual, out Matrix3D matrix)
        {
            matrix = Matrix3D.Identity;

            Viewport3DVisual?viewportVisual;
            Matrix3D         toWorld = GetWorldTransformationMatrix(visual, out viewportVisual);

            bool     success;
            Matrix3D toViewport = TryWorldToViewportTransform(viewportVisual, out success);

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

            toWorld.Append(toViewport);
            matrix = toWorld;
            return(true);
        }
Exemple #27
0
        /// <summary>
        /// Gets the object space to world space (or a parent object space) transformation for the given 3D visual.
        /// </summary>
        public static Matrix3D GetTransformationMatrix(DependencyObject visual, DependencyObject relativeTo = null)
        {
            Matrix3D matrix = Matrix3D.Identity;

            while (visual is ModelVisual3D)
            {
                Transform3D transform = (Transform3D)visual.GetValue(ModelVisual3D.TransformProperty);
                if (transform != null)
                {
                    matrix.Append(transform.Value);
                }

                visual = VisualTreeHelper.GetParent(visual);
                if (visual == relativeTo)
                {
                    break;
                }
            }

            return(matrix);
        }
        public static double GetRotationX(this Matrix3D matrix, double rotationZ, double rotationY)
        {
            // back off z rotation and y rotation
            Matrix3D matrix2 = new Matrix3D();

            matrix2.Append(matrix);
            matrix2 = matrix2.RotateXYZ(new Vector3D(0.0, 0.0, rotationZ * -1.0));
            Matrix3D matrix3 = new Matrix3D();

            matrix3.Append(matrix2);
            matrix3 = matrix3.RotateXYZ(new Vector3D(0.0, rotationY * -1.0, 0.0));

            Vector3D localY = matrix3.Transform(new Vector3D(0, 1, 0));

            localY.X = 0.0;
            double angle     = Vector3D.AngleBetween(localY, new Vector3D(0, 1, 0));
            double rotationX = localY.Z < 0 ? angle * -1.0 : angle;

            // rotation about the X axis
            return(rotationX);
        }
Exemple #29
0
        /// <summary>
        ///     Computes the transform from the inner space of the given
        ///     Visual3D to the 2D space of the Viewport3DVisual which
        ///     contains it.
        ///
        ///     The result will contain the transform of the given visual.
        ///
        ///     This method can fail if Camera.Transform is non-invertable
        ///     in which case the camera clip planes will be coincident and
        ///     nothing will render.  In this case success will be false.
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="success"></param>
        /// <returns></returns>
        public static Matrix3D TryTransformTo2DAncestor(DependencyObject visual, out Viewport3DVisual viewport, out bool success)
        {
            Matrix3D to2D = GetWorldTransformationMatrix(visual, out viewport);

            // 2012/6/6
            if (viewport == null)
            {
                success = false;
                return(ZeroMatrix);
            }

            Debug.Assert(viewport != null, "");

            to2D.Append(MathUtils.TryWorldToViewportTransform(viewport, out success));

            if (!success)
            {
                return(ZeroMatrix);
            }

            return(to2D);
        }
        // 3D transformation

        /// <summary>
        /// Creates a matrix that represents the transformation from the local coordinate system
        /// to another. This method supports three dimensional objects created via 'Sprite3D'.
        /// </summary>
        public Matrix3D GetTransformationMatrix3D(DisplayObject targetSpace)
        {
            DisplayObject currentObject;

            Matrix3D outM = Matrix3D.Create();

            if (targetSpace == this)
            {
                return(outM);
            }
            if (targetSpace == _parent || (targetSpace == null && _parent == null))
            {
                outM.CopyFrom(TransformationMatrix3D);
                return(outM);
            }
            if (targetSpace == null || targetSpace == Base)
            {
                // targetCoordinateSpace 'null' represents the target space of the base object.
                // -> move up from this to base

                currentObject = this;
                while (currentObject != targetSpace)
                {
                    outM.Append(currentObject.TransformationMatrix3D);
                    currentObject = currentObject._parent;
                }
                return(outM);
            }
            if (targetSpace._parent == this) // optimization
            {
                outM = targetSpace.GetTransformationMatrix3D(this);
                outM.Invert();
                return(outM);
            }

            // 1. find a common parent of this and the target space

            var commonParent = FindCommonParent(this, targetSpace);

            // 2. move up from this to common parent

            currentObject = this;
            while (currentObject != commonParent)
            {
                outM.Append(currentObject.TransformationMatrix3D);
                currentObject = currentObject._parent;
            }

            if (commonParent == targetSpace)
            {
                return(outM);
            }

            // 3. now move up from target until we reach the common parent

            var sHelperMatrix3D = Matrix3D.Create();

            currentObject = targetSpace;
            while (currentObject != commonParent)
            {
                sHelperMatrix3D.Append(currentObject.TransformationMatrix3D);
                currentObject = currentObject._parent;
            }

            // 4. now combine the two matrices

            sHelperMatrix3D.Invert();
            outM.Append(sHelperMatrix3D);

            return(outM);
        }