示例#1
0
        /// <inheritdoc/>
        public override Aabb GetAabb(Vector3F scale, Pose pose)
        {
            if (scale.X == scale.Y && scale.Y == scale.Z)
            {
                // Uniform scaling.

                // Get world axes in local space. They are equal to the rows of the orientation matrix.
                Matrix33F rotationMatrix = pose.Orientation;
                Vector3F  worldX         = rotationMatrix.GetRow(0);
                Vector3F  worldY         = rotationMatrix.GetRow(1);
                Vector3F  worldZ         = rotationMatrix.GetRow(2);

                // Get extreme points along positive axes.
                Vector3F halfExtent = Vector3F.Absolute(
                    new Vector3F(
                        Vector3F.Dot(GetSupportPointNormalized(worldX), worldX),
                        Vector3F.Dot(GetSupportPointNormalized(worldY), worldY),
                        Vector3F.Dot(GetSupportPointNormalized(worldZ), worldZ)));

                // Apply scale.
                halfExtent *= Math.Abs(scale.X);

                Vector3F minimum = pose.Position - halfExtent;
                Vector3F maximum = pose.Position + halfExtent;

                Debug.Assert(minimum <= maximum);

                return(new Aabb(minimum, maximum));
            }
            else
            {
                // Non-uniform scaling.
                return(base.GetAabb(scale, pose));
            }
        }
示例#2
0
        /// <summary>
        /// Gets the Euler angles for the given rotation.
        /// </summary>
        /// <param name="rotation">The rotation.</param>
        /// <returns>
        /// A vector with the three Euler angles in radians: (angle0, angle1, angle2).
        /// </returns>
        /// <remarks>
        /// <para>
        /// The Euler angles are computed for following order of rotations: The first rotations is about
        /// the x-axis. The second rotation is about the rotated y-axis after the first rotation. The
        /// last rotation is about the final z-axis.
        /// </para>
        /// <para>
        /// The Euler angles are unique if the second angle is less than +/- 90°. The limits for the
        /// rotation angles are [-180°, 180°] for the first and the third angle. And the limit for the
        /// second angle is [-90°, 90°].
        /// </para>
        /// </remarks>
        public static Vector3F GetEulerAngles(Matrix33F rotation)
        {
            // See book Geometric Tools, "Factoring Rotation Matrices as RxRyRz", pp. 848.
            Vector3F result = new Vector3F();

            float sinY = rotation.M02;

            if (sinY < 1.0f)
            {
                if (sinY > -1.0f)
                {
                    result.X = (float)Math.Atan2(-rotation.M12, rotation.M22);
                    result.Y = (float)Math.Asin(sinY);
                    result.Z = (float)Math.Atan2(-rotation.M01, rotation.M00);
                }
                else
                {
                    // Not a unique solution (thetaX - thetaZ is constant).
                    result.X = -(float)Math.Atan2(rotation.M10, rotation.M11);
                    result.Y = -ConstantsF.PiOver2;
                    result.Z = 0;
                }
            }
            else
            {
                // Not a unique solution (thetaX + thetaZ is constant).
                result.X = (float)Math.Atan2(rotation.M10, rotation.M11);
                result.Y = ConstantsF.PiOver2;
                result.Z = 0;
            }

            return(result);
        }
示例#3
0
        //--------------------------------------------------------------
        #region Creation & Cleanup
        //--------------------------------------------------------------
        #endregion


        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <inheritdoc/>
        protected override void OnSetup()
        {
            var   deltaTime      = Simulation.Settings.Timing.FixedTimeStep;
            float errorReduction = ConstraintHelper.ComputeErrorReduction(deltaTime, SpringConstant, DampingConstant);
            float softness       = ConstraintHelper.ComputeSoftness(deltaTime, SpringConstant, DampingConstant);

            // Get anchor orientations in world space.
            Matrix33F anchorOrientationA = BodyA.Pose.Orientation * AnchorOrientationALocal;
            Matrix33F anchorOrientationB = BodyB.Pose.Orientation * AnchorOrientationBLocal;

            Matrix33F relativeOrientation = anchorOrientationA.Transposed * anchorOrientationB;
            Vector3F  angles = ConstraintHelper.GetEulerAngles(relativeOrientation);

            // The constraint axes: See OneNote for a detailed derivation of these non-intuitive axes.
            var      xA = anchorOrientationA.GetColumn(0); // Anchor x-axis on A.
            var      zB = anchorOrientationB.GetColumn(2); // Anchor z-axis on B.
            Vector3F constraintAxisY = Vector3F.Cross(zB, xA);
            Vector3F constraintAxisX = Vector3F.Cross(constraintAxisY, zB);
            Vector3F constraintAxisZ = Vector3F.Cross(xA, constraintAxisY);

            SetupConstraint(0, angles[0], TargetAngles[0], constraintAxisX, deltaTime, errorReduction, softness);
            SetupConstraint(1, angles[1], TargetAngles[1], constraintAxisY, deltaTime, errorReduction, softness);
            SetupConstraint(2, angles[2], TargetAngles[2], constraintAxisZ, deltaTime, errorReduction, softness);

            // No warmstarting.
            _constraints[0].ConstraintImpulse = 0;
            _constraints[1].ConstraintImpulse = 0;
            _constraints[2].ConstraintImpulse = 0;
        }
示例#4
0
        /// <inheritdoc/>
        protected override void OnSetup()
        {
            // Get anchor pose/position in world space.
            Pose     anchorPoseA     = BodyA.Pose * AnchorPoseALocal;
            Vector3F anchorPositionB = BodyB.Pose.ToWorldPosition(AnchorPositionBLocal); // TODO: We could store rALocal and use ToWorldDirection instead of ToWorldPosition.

            // Compute anchor position on B relative to anchor pose of A.
            Vector3F relativePosition = anchorPoseA.ToLocalPosition(anchorPositionB);

            // The linear constraint axes are the fixed anchor axes of A!
            Matrix33F anchorOrientation = anchorPoseA.Orientation;

            Vector3F rA = anchorPoseA.Position - BodyA.PoseCenterOfMass.Position;
            Vector3F rB = anchorPositionB - BodyB.PoseCenterOfMass.Position;

            // Remember old states.
            LimitState oldXLimitState = _limitStates[0];
            LimitState oldYLimitState = _limitStates[1];
            LimitState oldZLimitState = _limitStates[2];

            SetupConstraint(0, relativePosition.X, anchorOrientation.GetColumn(0), rA, rB);
            SetupConstraint(1, relativePosition.Y, anchorOrientation.GetColumn(1), rA, rB);
            SetupConstraint(2, relativePosition.Z, anchorOrientation.GetColumn(2), rA, rB);

            Warmstart(0, oldXLimitState);
            Warmstart(1, oldYLimitState);
            Warmstart(2, oldZLimitState);
        }
示例#5
0
        /// <inheritdoc/>
        public override Aabb GetAabb(Vector3F scale, Pose pose)
        {
            Vector3F halfExtent = new Vector3F(_widthX / 2, _widthY / 2, _widthZ / 2) * Vector3F.Absolute(scale);

            if (pose == Pose.Identity)
            {
                return(new Aabb(-halfExtent, halfExtent));
            }

            // Get world axes in local space. They are equal to the rows of the orientation matrix.
            Matrix33F rotationMatrix = pose.Orientation;
            Vector3F  worldX         = rotationMatrix.GetRow(0);
            Vector3F  worldY         = rotationMatrix.GetRow(1);
            Vector3F  worldZ         = rotationMatrix.GetRow(2);

            // The half extent vector is in the +x/+y/+z octant of the world. We want to project
            // the extent onto the world axes. The half extent projected onto world x gives us the
            // x extent.
            // The world axes in local space could be in another world octant. We could now either find
            // out the in which octant the world axes is pointing and build the correct half extent vector
            // for this octant. OR we mirror the world axis vectors into the +x/+y/+z octant by taking
            // the absolute vector.
            worldX = Vector3F.Absolute(worldX);
            worldY = Vector3F.Absolute(worldY);
            worldZ = Vector3F.Absolute(worldZ);

            // Now we project the extent onto the world axes.
            Vector3F halfExtentWorld = new Vector3F(Vector3F.Dot(halfExtent, worldX),
                                                    Vector3F.Dot(halfExtent, worldY),
                                                    Vector3F.Dot(halfExtent, worldZ));

            return(new Aabb(pose.Position - halfExtentWorld, pose.Position + halfExtentWorld));
        }
示例#6
0
        /// <inheritdoc/>
        protected override void OnSetup()
        {
            // Get anchor orientations in world space.
            Matrix33F anchorOrientationA = BodyA.Pose.Orientation * AnchorOrientationALocal;
            Matrix33F anchorOrientationB = BodyB.Pose.Orientation * AnchorOrientationBLocal;

            // Get anchor orientation of B relative to A.
            Matrix33F relativeOrientation = anchorOrientationA.Transposed * anchorOrientationB;

            Vector3F angles = ConstraintHelper.GetEulerAngles(relativeOrientation);

            // The constraint axes: See OneNote for a detailed derivation of these non-intuitive axes.
            var      xA = anchorOrientationA.GetColumn(0); // Anchor x-axis on A.
            var      zB = anchorOrientationB.GetColumn(2); // Anchor z-axis on B.
            Vector3F constraintAxisY = Vector3F.Cross(zB, xA);
            Vector3F constraintAxisX = Vector3F.Cross(constraintAxisY, zB);
            Vector3F constraintAxisZ = Vector3F.Cross(xA, constraintAxisY);

            // Remember old states.
            LimitState oldXLimitState = _limitStates[0];
            LimitState oldYLimitState = _limitStates[1];
            LimitState oldZLimitState = _limitStates[2];

            SetupConstraint(0, angles.X, constraintAxisX);
            SetupConstraint(1, angles.Y, constraintAxisY);
            SetupConstraint(2, angles.Z, constraintAxisZ);

            Warmstart(0, oldXLimitState);
            Warmstart(1, oldYLimitState);
            Warmstart(2, oldZLimitState);
        }
示例#7
0
 public void IsRotation()
 {
     Assert.IsTrue(!Matrix33F.Zero.IsRotation);
     Assert.IsTrue(Matrix33F.Identity.IsRotation);
     Assert.IsTrue(Matrix33F.CreateRotation(new Vector3F(1, 2, 3).Normalized, 0.5f).IsRotation);
     Assert.IsTrue(!new Matrix33F(1, 0, 0, 0, 1, 0, 0, 0, -1).IsRotation);
 }
示例#8
0
        protected override Pose Read(ContentReader input, Pose existingInstance)
        {
            Vector3F  position    = input.ReadRawObject <Vector3F>();
            Matrix33F orientation = input.ReadRawObject <Matrix33F>();

            return(new Pose(position, orientation));
        }
示例#9
0
        /// <summary>
        /// Changes the mass to the given target mass.
        /// </summary>
        /// <param name="targetMass">The target mass.</param>
        /// <param name="mass">The mass.</param>
        /// <param name="inertia">The inertia.</param>
        private static void AdjustMass(float targetMass, ref float mass, ref Matrix33F inertia)
        {
            float scale = targetMass / mass;

            mass    = targetMass;
            inertia = inertia * scale;
        }
示例#10
0
        // Add a chain-like figure using TransformedFigure and CompositeFigure.
        private void CreateChain()
        {
            var ellipse = new EllipseFigure
            {
                IsFilled = false,
                RadiusX  = 1f,
                RadiusY  = 1f,
            };

            var compositeFigure = new CompositeFigure();

            for (int i = 0; i < 9; i++)
            {
                var transformedEllipse = new TransformedFigure(ellipse)
                {
                    Scale = new Vector3F(0.4f, 0.2f, 1),
                    Pose  = new Pose(new Vector3F(-2 + i * 0.5f, 0, 0), Matrix33F.CreateRotationX(ConstantsF.PiOver2 * (i % 2)))
                };
                compositeFigure.Children.Add(transformedEllipse);
            }

            _scene.Children.Add(new FigureNode(compositeFigure)
            {
                Name            = "Chain",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(0.1f),
                StrokeAlpha     = 1,
                PoseLocal       = new Pose(new Vector3F(0, 3, 0)),
            });
        }
示例#11
0
        public void SerializationBinary()
        {
            Matrix33F m1 = new Matrix33F(12, 23, 45,
                                         56, 67, 89,
                                         90, 12, 43.3f);
            Matrix33F m2;

            string fileName = "SerializationMatrix33F.bin";

            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }

            FileStream fs = new FileStream(fileName, FileMode.Create);

            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(fs, m1);
            fs.Close();

            fs        = new FileStream(fileName, FileMode.Open);
            formatter = new BinaryFormatter();
            m2        = (Matrix33F)formatter.Deserialize(fs);
            fs.Close();

            Assert.AreEqual(m1, m2);
        }
示例#12
0
        public void ToLocal()
        {
            Vector3F point0 = new Vector3F(1, 0.5f, 0.5f);
            Vector3F point1 = new Vector3F(0.5f, 1, 0.5f);
            Vector3F point2 = new Vector3F(0.5f, 0.5f, 1);
            Plane    plane  = new Plane(point0, point1, point2);

            Vector3F pointAbove = plane.Normal * plane.DistanceFromOrigin * 2;
            Vector3F pointBelow = plane.Normal * plane.DistanceFromOrigin * 0.5f;

            Assert.IsTrue(Vector3F.Dot(plane.Normal, pointAbove) > plane.DistanceFromOrigin);
            Assert.IsTrue(Vector3F.Dot(plane.Normal, pointBelow) < plane.DistanceFromOrigin);

            Pose pose = new Pose(new Vector3F(-5, 100, -20), Matrix33F.CreateRotation(new Vector3F(1, 2, 3), 0.123f));

            point0     = pose.ToLocalPosition(point0);
            point1     = pose.ToLocalPosition(point1);
            point2     = pose.ToLocalPosition(point2);
            pointAbove = pose.ToLocalPosition(pointAbove);
            pointBelow = pose.ToLocalPosition(pointBelow);
            plane.ToLocal(ref pose);

            Assert.IsTrue(plane.Normal.IsNumericallyNormalized);

            Vector3F dummy;

            Assert.IsTrue(GeometryHelper.GetClosestPoint(plane, point0, out dummy));
            Assert.IsTrue(GeometryHelper.GetClosestPoint(plane, point1, out dummy));
            Assert.IsTrue(GeometryHelper.GetClosestPoint(plane, point2, out dummy));
            Assert.IsTrue(Vector3F.Dot(plane.Normal, pointAbove) > plane.DistanceFromOrigin);
            Assert.IsTrue(Vector3F.Dot(plane.Normal, pointBelow) < plane.DistanceFromOrigin);
        }
示例#13
0
        public void MultiplyTransposed()
        {
            var m = RandomHelper.Random.NextMatrix33F(1, 10);
            var v = RandomHelper.Random.NextVector3F(1, 10);

            Assert.AreEqual(m.Transposed * v, Matrix33F.MultiplyTransposed(m, v));
        }
示例#14
0
        public void SerializationXml()
        {
            Matrix33F m1 = new Matrix33F(12, 23, 45,
                                         67, 89, 90,
                                         43, 65, 87.3f);
            Matrix33F m2;

            string fileName = "SerializationMatrix33F.xml";

            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }

            XmlSerializer serializer = new XmlSerializer(typeof(Matrix33F));
            StreamWriter  writer     = new StreamWriter(fileName);

            serializer.Serialize(writer, m1);
            writer.Close();

            serializer = new XmlSerializer(typeof(Matrix33F));
            FileStream fileStream = new FileStream(fileName, FileMode.Open);

            m2 = (Matrix33F)serializer.Deserialize(fileStream);
            Assert.AreEqual(m1, m2);
        }
示例#15
0
        public void MultiplyMatrix()
        {
            Matrix33F m = new Matrix33F(12, 23, 45,
                                        67, 89, 90,
                                        43, 65, 87);

            Assert.AreEqual(Matrix33F.Zero, Matrix33F.Multiply(m, Matrix33F.Zero));
            Assert.AreEqual(Matrix33F.Zero, Matrix33F.Multiply(Matrix33F.Zero, m));
            Assert.AreEqual(m, Matrix33F.Multiply(m, Matrix33F.Identity));
            Assert.AreEqual(m, Matrix33F.Multiply(Matrix33F.Identity, m));
            Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.Identity, Matrix33F.Multiply(m, m.Inverse)));
            Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.Identity, Matrix33F.Multiply(m.Inverse, m)));

            Matrix33F m1 = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
            Matrix33F m2 = new Matrix33F(12, 23, 45,
                                         67, 89, 90,
                                         43, 65, 87);
            Matrix33F result = Matrix33F.Multiply(m1, m2);

            for (int column = 0; column < 3; column++)
            {
                for (int row = 0; row < 3; row++)
                {
                    Assert.AreEqual(Vector3F.Dot(m1.GetRow(row), m2.GetColumn(column)), result[row, column]);
                }
            }
        }
示例#16
0
        public void AbsoluteStatic()
        {
            Matrix33F m = new Matrix33F(-1, -2, -3, -4, -5, -6, -7, -8, -9);
              Matrix33F absoluteM = Matrix33F.Absolute(m);

              Assert.AreEqual(1, absoluteM.M00);
              Assert.AreEqual(2, absoluteM.M01);
              Assert.AreEqual(3, absoluteM.M02);
              Assert.AreEqual(4, absoluteM.M10);
              Assert.AreEqual(5, absoluteM.M11);
              Assert.AreEqual(6, absoluteM.M12);
              Assert.AreEqual(7, absoluteM.M20);
              Assert.AreEqual(8, absoluteM.M21);
              Assert.AreEqual(9, absoluteM.M22);

              m = new Matrix33F(1, 2, 3, 4, 5, 6, 7, 8, 9);
              absoluteM = Matrix33F.Absolute(m);
              Assert.AreEqual(1, absoluteM.M00);
              Assert.AreEqual(2, absoluteM.M01);
              Assert.AreEqual(3, absoluteM.M02);
              Assert.AreEqual(4, absoluteM.M10);
              Assert.AreEqual(5, absoluteM.M11);
              Assert.AreEqual(6, absoluteM.M12);
              Assert.AreEqual(7, absoluteM.M20);
              Assert.AreEqual(8, absoluteM.M21);
              Assert.AreEqual(9, absoluteM.M22);
        }
示例#17
0
        public SmokeSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            // Create a single particle system and add it multiple times to the scene
            // graph ("instancing"). By default, all instances look identical. The
            // properties ParticleSystemNode.Color/Alpha/AngleOffset can be used to
            // render the particles with some variations.
            var particleSystem = Smoke.Create(ContentManager);

            ParticleSystemService.ParticleSystems.Add(particleSystem);

            _particleSystemNode0 = new ParticleSystemNode(particleSystem);
            GraphicsScreen.Scene.Children.Add(_particleSystemNode0);

            _particleSystemNode1             = new ParticleSystemNode(particleSystem);
            _particleSystemNode1.PoseWorld   = new Pose(new Vector3F(5, 0, -5));
            _particleSystemNode1.Color       = new Vector3F(0.9f, 0.8f, 0.7f);
            _particleSystemNode1.Alpha       = 0.8f;
            _particleSystemNode1.AngleOffset = 0.3f;
            GraphicsScreen.Scene.Children.Add(_particleSystemNode1);

            _particleSystemNode2             = new ParticleSystemNode(particleSystem);
            _particleSystemNode2.PoseWorld   = new Pose(new Vector3F(-10, 5, -5), Matrix33F.CreateRotationZ(-ConstantsF.PiOver2));
            _particleSystemNode2.Color       = new Vector3F(0.5f, 0.5f, 0.5f);
            _particleSystemNode2.AngleOffset = 0.6f;
            GraphicsScreen.Scene.Children.Add(_particleSystemNode2);
        }
示例#18
0
        /// <summary>
        /// Diagonalizes the inertia matrix.
        /// </summary>
        /// <param name="inertia">The inertia matrix.</param>
        /// <param name="inertiaDiagonal">The inertia of the principal axes.</param>
        /// <param name="rotation">
        /// The rotation that rotates from principal axis space to parent/world space.
        /// </param>
        /// <remarks>
        /// All valid inertia matrices can be transformed into a coordinate space where all elements
        /// non-diagonal matrix elements are 0. The axis of this special space are the principal axes.
        /// </remarks>
        internal static void DiagonalizeInertia(Matrix33F inertia, out Vector3F inertiaDiagonal, out Matrix33F rotation)
        {
            // Alternatively we could use Jacobi transformation (iterative method, see Bullet/btMatrix3x3.diagonalize()
            // and Numerical Recipes book) or we could find the eigenvalues using the characteristic
            // polynomial which is a cubic polynomial and then solve for the eigenvectors (see Numeric
            // Recipes and "Mathematics for 3D Game Programming and Computer Graphics" chapter ray-tracing
            // for cubic equations and computation of bounding boxes.

            // Perform eigenvalue decomposition.
            var eigenValueDecomposition = new EigenvalueDecompositionF(inertia.ToMatrixF());

            inertiaDiagonal = eigenValueDecomposition.RealEigenvalues.ToVector3F();
            rotation        = eigenValueDecomposition.V.ToMatrix33F();

            if (!rotation.IsRotation)
            {
                // V is orthogonal but not necessarily a rotation. If it is no rotation
                // we have to swap two columns.
                MathHelper.Swap(ref inertiaDiagonal.Y, ref inertiaDiagonal.Z);

                Vector3F dummy = rotation.GetColumn(1);
                rotation.SetColumn(1, rotation.GetColumn(2));
                rotation.SetColumn(2, dummy);

                Debug.Assert(rotation.IsRotation);
            }
        }
示例#19
0
        public void SerializationXml2()
        {
            Matrix33F m1 = new Matrix33F(12, 23, 45,
                                         56, 67, 89,
                                         90, 12, 43.3f);
            Matrix33F m2;

            string fileName = "SerializationMatrix33F_DataContractSerializer.xml";

            if (File.Exists(fileName))
            {
                File.Delete(fileName);
            }

            var serializer = new DataContractSerializer(typeof(Matrix33F));

            using (var stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write))
                using (var writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
                    serializer.WriteObject(writer, m1);

            using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                using (var reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()))
                    m2 = (Matrix33F)serializer.ReadObject(reader);

            Assert.AreEqual(m1, m2);
        }
        private void SetCameraPose()
        {
            var vehiclePose = _vehicle.Pose;

            if (_useSpectatorView)
            {
                // Spectator Mode:
                // Camera is looking at the car from a fixed location in the level.
                Vector3F position = new Vector3F(10, 8, 10);
                Vector3F target   = vehiclePose.Position;
                Vector3F up       = Vector3F.UnitY;

                // Set the new camera view matrix. (Setting the View matrix changes the Pose.
                // The pose is simply the inverse of the view matrix).
                CameraNode.View = Matrix44F.CreateLookAt(position, target, up);
            }
            else
            {
                // Player Camera:
                // Camera moves with the car. The look direction can be changed by moving the mouse.
                Matrix33F yaw         = Matrix33F.CreateRotationY(_yaw);
                Matrix33F pitch       = Matrix33F.CreateRotationX(_pitch);
                Matrix33F orientation = vehiclePose.Orientation * yaw * pitch;
                Vector3F  forward     = orientation * -Vector3F.UnitZ;
                Vector3F  up          = Vector3F.UnitY;
                Vector3F  position    = vehiclePose.Position - 10 * forward + 5 * up;
                Vector3F  target      = vehiclePose.Position + 1 * up;

                CameraNode.View = Matrix44F.CreateLookAt(position, target, up);
            }
        }
示例#21
0
        public void AbsoluteStatic()
        {
            Matrix33F m         = new Matrix33F(-1, -2, -3, -4, -5, -6, -7, -8, -9);
            Matrix33F absoluteM = Matrix33F.Absolute(m);

            Assert.AreEqual(1, absoluteM.M00);
            Assert.AreEqual(2, absoluteM.M01);
            Assert.AreEqual(3, absoluteM.M02);
            Assert.AreEqual(4, absoluteM.M10);
            Assert.AreEqual(5, absoluteM.M11);
            Assert.AreEqual(6, absoluteM.M12);
            Assert.AreEqual(7, absoluteM.M20);
            Assert.AreEqual(8, absoluteM.M21);
            Assert.AreEqual(9, absoluteM.M22);

            m         = new Matrix33F(1, 2, 3, 4, 5, 6, 7, 8, 9);
            absoluteM = Matrix33F.Absolute(m);
            Assert.AreEqual(1, absoluteM.M00);
            Assert.AreEqual(2, absoluteM.M01);
            Assert.AreEqual(3, absoluteM.M02);
            Assert.AreEqual(4, absoluteM.M10);
            Assert.AreEqual(5, absoluteM.M11);
            Assert.AreEqual(6, absoluteM.M12);
            Assert.AreEqual(7, absoluteM.M20);
            Assert.AreEqual(8, absoluteM.M21);
            Assert.AreEqual(9, absoluteM.M22);
        }
示例#22
0
        /// <summary>
        /// Diagonalizes the inertia matrix.
        /// </summary>
        /// <param name="inertia">The inertia matrix.</param>
        /// <param name="inertiaDiagonal">The inertia of the principal axes.</param>
        /// <param name="rotation">
        /// The rotation that rotates from principal axis space to parent/world space.
        /// </param>
        /// <remarks>
        /// All valid inertia matrices can be transformed into a coordinate space where all elements
        /// non-diagonal matrix elements are 0. The axis of this special space are the principal axes.
        /// </remarks>
        internal static void DiagonalizeInertia(Matrix33F inertia, out Vector3F inertiaDiagonal, out Matrix33F rotation)
        {
            // Alternatively we could use Jacobi transformation (iterative method, see Bullet/btMatrix3x3.diagonalize()
              // and Numerical Recipes book) or we could find the eigenvalues using the characteristic
              // polynomial which is a cubic polynomial and then solve for the eigenvectors (see Numeric
              // Recipes and "Mathematics for 3D Game Programming and Computer Graphics" chapter ray-tracing
              // for cubic equations and computation of bounding boxes.

              // Perform eigenvalue decomposition.
              var eigenValueDecomposition = new EigenvalueDecompositionF(inertia.ToMatrixF());
              inertiaDiagonal = eigenValueDecomposition.RealEigenvalues.ToVector3F();
              rotation = eigenValueDecomposition.V.ToMatrix33F();

              if (!rotation.IsRotation)
              {
            // V is orthogonal but not necessarily a rotation. If it is no rotation
            // we have to swap two columns.
            MathHelper.Swap(ref inertiaDiagonal.Y, ref inertiaDiagonal.Z);

            Vector3F dummy = rotation.GetColumn(1);
            rotation.SetColumn(1, rotation.GetColumn(2));
            rotation.SetColumn(2, dummy);

            Debug.Assert(rotation.IsRotation);
              }
        }
示例#23
0
        public void Properties()
        {
            Matrix33F m = new Matrix33F(rowMajor, MatrixOrder.RowMajor);

            Assert.AreEqual(1.0f, m.M00);
            Assert.AreEqual(2.0f, m.M01);
            Assert.AreEqual(3.0f, m.M02);
            Assert.AreEqual(4.0f, m.M10);
            Assert.AreEqual(5.0f, m.M11);
            Assert.AreEqual(6.0f, m.M12);
            Assert.AreEqual(7.0f, m.M20);
            Assert.AreEqual(8.0f, m.M21);
            Assert.AreEqual(9.0f, m.M22);

            m     = Matrix33F.Zero;
            m.M00 = 1.0f;
            m.M01 = 2.0f;
            m.M02 = 3.0f;
            m.M10 = 4.0f;
            m.M11 = 5.0f;
            m.M12 = 6.0f;
            m.M20 = 7.0f;
            m.M21 = 8.0f;
            m.M22 = 9.0f;
            Assert.AreEqual(new Matrix33F(rowMajor, MatrixOrder.RowMajor), m);
        }
        public SkeletonMappingSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            // Get dude model and start animation on the dude.
            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");

            _dudeMeshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _dudeMeshNode.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_dudeMeshNode);
            GraphicsScreen.Scene.Children.Add(_dudeMeshNode);

            var animations       = _dudeMeshNode.Mesh.Animations;
            var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First())
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_dudeMeshNode.SkeletonPose);

            // Get marine model - do not start any animations on the marine model.
            modelNode                 = ContentManager.Load <ModelNode>("Marine/PlayerMarine");
            _marineMeshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _marineMeshNode.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_marineMeshNode);
            GraphicsScreen.Scene.Children.Add(_marineMeshNode);

            CreateSkeletonMapper();
        }
示例#25
0
        //--------------------------------------------------------------
        #region Creation & Cleanup
        //--------------------------------------------------------------

        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainDecalLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            {
                throw new ArgumentNullException("graphicService");
            }

            // Use a down orientation per default.
            Pose = new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2));

            var effect = graphicService.Content.Load <Effect>("DigitalRune/Terrain/TerrainDecalLayer");

            Material = new Material
            {
                { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
            };

            FadeOutStart       = int.MaxValue;
            FadeOutEnd         = int.MaxValue;
            Width              = 1;
            Height             = 1;
            DiffuseColor       = new Vector3F(1, 1, 1);
            SpecularColor      = new Vector3F(1, 1, 1);
            SpecularPower      = 10;
            Alpha              = 1;
            DiffuseTexture     = graphicService.GetDefaultTexture2DWhite();
            SpecularTexture    = graphicService.GetDefaultTexture2DBlack();
            NormalTexture      = graphicService.GetDefaultNormalTexture();
            HeightTextureScale = 1;
            HeightTexture      = graphicService.GetDefaultTexture2DBlack();

            UpdateAabb();
        }
示例#26
0
        public void Constructors()
        {
            Matrix33F m = new Matrix33F(1.0f, 2.0f, 3.0f,
                                        4.0f, 5.0f, 6.0f,
                                        7.0f, 8.0f, 9.0f);

            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }

            m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }

            m = new Matrix33F(rowMajor, MatrixOrder.RowMajor);
            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }

            m = new Matrix33F(new List <float>(columnMajor), MatrixOrder.ColumnMajor);
            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }

            m = new Matrix33F(new List <float>(rowMajor), MatrixOrder.RowMajor);
            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }

            m = new Matrix33F(new float[3, 3] {
                { 1, 2, 3 },
                { 4, 5, 6 },
                { 7, 8, 9 }
            });
            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }

            m = new Matrix33F(new float[3][] { new float[3] {
                                                   1, 2, 3
                                               },
                                               new float[3] {
                                                   4, 5, 6
                                               },
                                               new float[3] {
                                                   7, 8, 9
                                               } });
            for (int i = 0; i < 9; i++)
            {
                Assert.AreEqual(rowMajor[i], m[i]);
            }
        }
示例#27
0
        public SkinnedEffectSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            GraphicsScreen.ClearBackground = true;
            GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
            SetCamera(new Vector3F(1, 1, 3), 0.2f, 0);

            // Create a sky mesh and add an instance of this mesh to the scene.
            var skyMesh = ProceduralSkyDome.CreateMesh(GraphicsService, ContentManager.Load <Texture2D>("sky"));

            _sky      = new MeshNode(skyMesh);
            _sky.Name = "Sky"; // Always set a name - very useful for debugging!
            GraphicsScreen.Scene.Children.Add(_sky);

            // Load the skinned model. This model is processed using the DigitalRune Model
            // Processor - not the default XNA model processor!
            // In the folder that contains dude.fbx, there are several XML files (*.drmdl and *.drmat)
            // which define the materials of the model. These material description files are
            // automatically processed by the DigitalRune Model Processor. Please browse
            // to the content folder and have a look at the *.drmdl and *.drmat files.
            var dudeModel = ContentManager.Load <ModelNode>("Dude/Dude");

            dudeModel           = dudeModel.Clone();
            dudeModel.PoseWorld = new Pose(Matrix33F.CreateRotationY(ConstantsF.Pi));
            GraphicsScreen.Scene.Children.Add(dudeModel);

            // The dude model consists of a single mesh.
            var dudeMeshNode = dudeModel.GetSubtree().OfType <MeshNode>().First();
            var mesh         = dudeMeshNode.Mesh;

            /*
             * // The dude mesh consists of different materials (head, eyes, torso, ...).
             * // We could change some of the material properties...
             * foreach (var material in mesh.Materials)
             * {
             *  // Get all SkinnedEffectBindings which wrap the XNA SkinnedEffect.
             *  // A material can consist of several effects - one effect for each render pass.
             *  // (Per default there is only one render pass called "Default".)
             *  foreach (var effectBinding in material.EffectBindings.OfType<SkinnedEffectBinding>())
             *  {
             *    // We could change effect parameters here, for example:
             *    effectBinding.PreferPerPixelLighting = true;
             *  }
             * }
             */

            // The DigitalRune Model Processor also loads animations.
            // Start the first animation of the dude and let it loop forever.
            // (We keep the animation controller to be able to stop the animation in
            // Dispose() below.)
            var timeline = new TimelineClip(mesh.Animations.Values.First())
            {
                Duration     = TimeSpan.MaxValue,
                LoopBehavior = LoopBehavior.Cycle,
            };

            _animationController = AnimationService.StartAnimation(timeline, (IAnimatableProperty)dudeMeshNode.SkeletonPose);
        }
示例#28
0
        public void GetColumn()
        {
            Matrix33F m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);

            Assert.AreEqual(new Vector3F(1.0f, 4.0f, 7.0f), m.GetColumn(0));
            Assert.AreEqual(new Vector3F(2.0f, 5.0f, 8.0f), m.GetColumn(1));
            Assert.AreEqual(new Vector3F(3.0f, 6.0f, 9.0f), m.GetColumn(2));
        }
示例#29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CloudMapLayer" /> struct.
 /// </summary>
 /// <param name="texture">The <see cref="Texture" />.</param>
 /// <param name="textureMatrix">The <see cref="TextureMatrix" />.</param>
 /// <param name="densityOffset">The <see cref="DensityOffset" />.</param>
 /// <param name="densityScale">The <see cref="DensityScale" />.</param>
 /// <param name="animationSpeed">The <see cref="AnimationSpeed"/>.</param>
 public CloudMapLayer(Texture2D texture, Matrix33F textureMatrix, float densityOffset, float densityScale, float animationSpeed)
 {
     Texture        = texture;
     TextureMatrix  = textureMatrix;
     DensityScale   = densityScale;
     DensityOffset  = densityOffset;
     AnimationSpeed = animationSpeed;
 }
示例#30
0
        public void GetRow()
        {
            Matrix33F m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);

            Assert.AreEqual(new Vector3F(1.0f, 2.0f, 3.0f), m.GetRow(0));
            Assert.AreEqual(new Vector3F(4.0f, 5.0f, 6.0f), m.GetRow(1));
            Assert.AreEqual(new Vector3F(7.0f, 8.0f, 9.0f), m.GetRow(2));
        }
示例#31
0
 internal static Pose ToDigitalRune(this Matrix4x4 matrix)
 {
     var position = new Vector3F(matrix.M30, matrix.M31, matrix.M32);
     var orientation = new Matrix33F(matrix.M00, matrix.M10, matrix.M20,
                                     matrix.M01, matrix.M11, matrix.M21,
                                     matrix.M02, matrix.M12, matrix.M22);
     return new Pose(position, orientation);
 }
示例#32
0
        public void Transposed()
        {
            Matrix33F m  = new Matrix33F(rowMajor, MatrixOrder.RowMajor);
            Matrix33F mt = new Matrix33F(rowMajor, MatrixOrder.ColumnMajor);

            Assert.AreEqual(mt, m.Transposed);
            Assert.AreEqual(Matrix33F.Identity, Matrix33F.Identity.Transposed);
        }
示例#33
0
        public void CrossProductMatrix()
        {
            Vector3F  v = new Vector3F(-1.0f, -2.0f, -3.0f);
            Vector3F  w = new Vector3F(4.0f, 5.0f, 6.0f);
            Matrix33F m = v.ToCrossProductMatrix();

            Assert.AreEqual(Vector3F.Cross(v, w), v.ToCrossProductMatrix() * w);
        }
示例#34
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CloudMapLayer" /> struct.
 /// </summary>
 /// <param name="texture">The <see cref="Texture" />.</param>
 /// <param name="textureMatrix">The <see cref="TextureMatrix" />.</param>
 /// <param name="densityOffset">The <see cref="DensityOffset" />.</param>
 /// <param name="densityScale">The <see cref="DensityScale" />.</param>
 /// <param name="animationSpeed">The <see cref="AnimationSpeed"/>.</param>
 public CloudMapLayer(Texture2D texture, Matrix33F textureMatrix, float densityOffset, float densityScale, float animationSpeed)
 {
     Texture = texture;
       TextureMatrix = textureMatrix;
       DensityScale = densityScale;
       DensityOffset = densityOffset;
       AnimationSpeed = animationSpeed;
 }
示例#35
0
        /// <overloads>
        /// <summary>
        /// Computes the covariance matrix for a list of points.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Computes the covariance matrix for a list of 3-dimensional points (single-precision).
        /// </summary>
        /// <param name="points">The points.</param>
        /// <returns>The covariance matrix.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="points"/> is <see langword="null"/>.
        /// </exception>
        public static Matrix33F ComputeCovarianceMatrix(IList<Vector3F> points)
        {
            // Notes: See "Real-Time Collision Detection" p. 93

              if (points == null)
            throw new ArgumentNullException("points");

              int numberOfPoints = points.Count;
              float oneOverNumberOfPoints = 1f / numberOfPoints;

              // Compute the center of mass.
              Vector3F centerOfMass = Vector3F.Zero;
              for (int i = 0; i < numberOfPoints; i++)
            centerOfMass += points[i];
              centerOfMass *= oneOverNumberOfPoints;

              // Compute covariance matrix.
              float c00 = 0;
              float c11 = 0;
              float c22 = 0;
              float c01 = 0;
              float c02 = 0;
              float c12 = 0;

              for (int i = 0; i < numberOfPoints; i++)
              {
            // Translate points so that center of mass is at origin.
            Vector3F p = points[i] - centerOfMass;

            // Compute covariance of translated point.
            c00 += p.X * p.X;
            c11 += p.Y * p.Y;
            c22 += p.Z * p.Z;
            c01 += p.X * p.Y;
            c02 += p.X * p.Z;
            c12 += p.Y * p.Z;
              }
              c00 *= oneOverNumberOfPoints;
              c11 *= oneOverNumberOfPoints;
              c22 *= oneOverNumberOfPoints;
              c01 *= oneOverNumberOfPoints;
              c02 *= oneOverNumberOfPoints;
              c12 *= oneOverNumberOfPoints;

              Matrix33F covarianceMatrix = new Matrix33F(c00, c01, c02,
                                                 c01, c11, c12,
                                                 c02, c12, c22);
              return covarianceMatrix;
        }
示例#36
0
        /// <summary>
        /// Renders a skybox.
        /// </summary>
        /// <param name="texture">The cube map with the sky texture.</param>
        /// <param name="orientation">The orientation of the skybox.</param>
        /// <param name="exposure">The exposure factor that is multiplied to the cube map values to change the brightness.
        /// (Usually 1 or higher).</param>
        /// <param name="context">
        /// The render context. (<see cref="RenderContext.CameraNode"/> needs to be set.)
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="texture"/> or <paramref name="context"/> is <see langword="null"/>.
        /// </exception>
        public void Render(TextureCube texture, Matrix33F orientation, float exposure, RenderContext context)
        {
            if (texture == null)
            throw new ArgumentNullException("texture");
              if (context == null)
            throw new ArgumentNullException("context");

              context.Validate(_effect);
              context.ThrowIfCameraMissing();

              var graphicsDevice = context.GraphicsService.GraphicsDevice;
              if (graphicsDevice.GraphicsProfile == GraphicsProfile.Reach)
            RenderReach(texture, orientation, exposure, context);
              else
            RenderHiDef(texture, orientation, exposure, context);
        }
示例#37
0
        //--------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="CloudMap" /> class.
        /// </summary>
        public LayeredCloudMap()
        {
            Coverage = 0.5f;
              Density = 10;
              Size = 1024;
              Seed = 1234567;

              // Initialize with 8 octaves of static noise.
              Layers = new CloudMapLayer[8];
              var scale = new Matrix33F(0.2f, 0, 0,
                                0, 0.2f, 0,
                                0, 0, 1);
              Layers[0] = new CloudMapLayer(null, scale * new Matrix33F(1, 0, 0, 0, 1, 0, 0, 0, 1), -0.5f, 1.0f, 0);
              Layers[1] = new CloudMapLayer(null, scale * new Matrix33F(2, 0, 0, 0, 2, 0, 0, 0, 1), -0.5f, 1.0f / 2.0f, 0);
              Layers[2] = new CloudMapLayer(null, scale * new Matrix33F(4, 0, 0, 0, 4, 0, 0, 0, 1), -0.5f, 1.0f / 4.0f, 0);
              Layers[3] = new CloudMapLayer(null, scale * new Matrix33F(8, 0, 0, 0, 8, 0, 0, 0, 1), -0.5f, 1.0f / 8.0f, 0);
              Layers[4] = new CloudMapLayer(null, scale * new Matrix33F(16, 0, 0, 0, 16, 0, 0, 0, 1), -0.5f, 1.0f / 16.0f, 0);
              Layers[5] = new CloudMapLayer(null, scale * new Matrix33F(32, 0, 0, 0, 32, 0, 0, 0, 1), -0.5f, 1.0f / 32.0f, 0);
              Layers[6] = new CloudMapLayer(null, scale * new Matrix33F(64, 0, 0, 0, 64, 0, 0, 0, 1), -0.5f, 1.0f / 64.0f, 0);
              Layers[7] = new CloudMapLayer(null, scale * new Matrix33F(128, 0, 0, 0, 128, 0, 0, 0, 1), -0.5f, 1.0f / 128.0f, 0);
        }
示例#38
0
        public void MultiplyMatrixOperator()
        {
            Matrix33F m = new Matrix33F(12, 23, 45,
                                67, 89, 90,
                                43, 65, 87);
              Assert.AreEqual(Matrix33F.Zero, m * Matrix33F.Zero);
              Assert.AreEqual(Matrix33F.Zero, Matrix33F.Zero * m);
              Assert.AreEqual(m, m * Matrix33F.Identity);
              Assert.AreEqual(m, Matrix33F.Identity * m);
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.Identity, m * m.Inverse));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.Identity, m.Inverse * m));

              Matrix33F m1 = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
              Matrix33F m2 = new Matrix33F(12, 23, 45,
                                 67, 89, 90,
                                 43, 65, 87);
              Matrix33F result = m1 * m2;
              for (int column = 0; column < 3; column++)
            for (int row = 0; row < 3; row++)
              Assert.AreEqual(Vector3F.Dot(m1.GetRow(row), m2.GetColumn(column)), result[row, column]);
        }
示例#39
0
        public void MultiplicationOperator()
        {
            float s = 0.1234f;
              Matrix33F m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
              m = s * m;
              for (int i = 0; i < 9; i++)
            Assert.AreEqual(rowMajor[i] * s, m[i]);

              m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
              m = m * s;
              for (int i = 0; i < 9; i++)
            Assert.AreEqual(rowMajor[i] * s, m[i]);
        }
示例#40
0
 private static void TryToMakeIdentityMatrix(ref Matrix33F m)
 {
     // If the rotated space is parallel to the world space, then we want to use
       // the identity matrix directly.
       if (Numeric.AreEqual(1, Math.Abs(m.M00) + Math.Abs(m.M10) + Math.Abs(m.M20))      // Is the first column UnitX, UnitY or UnitZ?
       && Numeric.AreEqual(1, Math.Abs(m.M01) + Math.Abs(m.M11) + Math.Abs(m.M21)))  // Is the second column UnitX, UnitY or UnitZ?
       {
     m = Matrix33F.Identity;
       }
 }
示例#41
0
        public static void GetMass(ITriangleMesh mesh, out float mass, out Vector3F centerOfMass, out Matrix33F inertia)
        {
            if (mesh == null)
            throw new ArgumentNullException("mesh");

              // Integral variables.
              float i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0, i8 = 0, i9 = 0;

              int numberOfTriangles = mesh.NumberOfTriangles;
              for (int triangleIndex = 0; triangleIndex < numberOfTriangles; triangleIndex++)
              {
            var triangle = mesh.GetTriangle(triangleIndex);

            // Vertex coordinates.
            Vector3F v0 = triangle.Vertex0;
            Vector3F v1 = triangle.Vertex1;
            Vector3F v2 = triangle.Vertex2;

            // Edges and cross products of edges
            Vector3F a = v1 - v0;
            Vector3F b = v2 - v0;
            Vector3F d = Vector3F.Cross(a, b);

            // Compute integral terms.
            float f1x, f2x, f3x, g0x, g1x, g2x;
            ComputePolyhedronMassSubExpressions(v0.X, v1.X, v2.X, out f1x, out f2x, out f3x, out g0x, out g1x, out g2x);
            float f1y, f2y, f3y, g0y, g1y, g2y;
            ComputePolyhedronMassSubExpressions(v0.Y, v1.Y, v2.Y, out f1y, out f2y, out f3y, out g0y, out g1y, out g2y);
            float f1z, f2z, f3z, g0z, g1z, g2z;
            ComputePolyhedronMassSubExpressions(v0.Z, v1.Z, v2.Z, out f1z, out f2z, out f3z, out g0z, out g1z, out g2z);

            // Update integrals.
            i0 += d.X * f1x;
            i1 += d.X * f2x;
            i2 += d.Y * f2y;
            i3 += d.Z * f2z;
            i4 += d.X * f3x;
            i5 += d.Y * f3y;
            i6 += d.Z * f3z;
            i7 += d.X * (v0.Y * g0x + v1.Y * g1x + v2.Y * g2x);
            i8 += d.Y * (v0.Z * g0y + v1.Z * g1y + v2.Z * g2y);
            i9 += d.Z * (v0.X * g0z + v1.X * g1z + v2.X * g2z);
              }

              i0 /= 6.0f;
              i1 /= 24.0f;
              i2 /= 24.0f;
              i3 /= 24.0f;
              i4 /= 60.0f;
              i5 /= 60.0f;
              i6 /= 60.0f;
              i7 /= 120.0f;
              i8 /= 120.0f;
              i9 /= 120.0f;

              mass = i0;

              centerOfMass = 1.0f / mass * new Vector3F(i1, i2, i3);
              // Clamp to zero.
              if (Numeric.IsZero(centerOfMass.X))
            centerOfMass.X = 0;
              if (Numeric.IsZero(centerOfMass.Y))
            centerOfMass.Y = 0;
              if (Numeric.IsZero(centerOfMass.Z))
            centerOfMass.Z = 0;

              // Inertia around the world origin.
              inertia.M00 = i5 + i6;
              inertia.M11 = i4 + i6;
              inertia.M22 = i4 + i5;
              inertia.M01 = inertia.M10 = Numeric.IsZero(i7) ? 0 : -i7;
              inertia.M12 = inertia.M21 = Numeric.IsZero(i8) ? 0 : -i8;
              inertia.M02 = inertia.M20 = Numeric.IsZero(i9) ? 0 : -i9;

              // Inertia around center of mass.
              inertia = GetUntranslatedMassInertia(mass, inertia, centerOfMass);
        }
示例#42
0
 public void Addition()
 {
     Matrix33F m1 = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
       Matrix33F m2 = Matrix33F.One;
       Matrix33F result = Matrix33F.Add(m1, m2);
       for (int i = 0; i < 9; i++)
     Assert.AreEqual(rowMajor[i] + 1.0f, result[i]);
 }
示例#43
0
        public void Properties()
        {
            Matrix33F m = new Matrix33F(rowMajor, MatrixOrder.RowMajor);
              Assert.AreEqual(1.0f, m.M00);
              Assert.AreEqual(2.0f, m.M01);
              Assert.AreEqual(3.0f, m.M02);
              Assert.AreEqual(4.0f, m.M10);
              Assert.AreEqual(5.0f, m.M11);
              Assert.AreEqual(6.0f, m.M12);
              Assert.AreEqual(7.0f, m.M20);
              Assert.AreEqual(8.0f, m.M21);
              Assert.AreEqual(9.0f, m.M22);

              m = Matrix33F.Zero;
              m.M00 = 1.0f;
              m.M01 = 2.0f;
              m.M02 = 3.0f;
              m.M10 = 4.0f;
              m.M11 = 5.0f;
              m.M12 = 6.0f;
              m.M20 = 7.0f;
              m.M21 = 8.0f;
              m.M22 = 9.0f;
              Assert.AreEqual(new Matrix33F(rowMajor, MatrixOrder.RowMajor), m);
        }
示例#44
0
 public void InverseWithNearSingularMatrix()
 {
     Matrix33F m = new Matrix33F(0.0001f, 0, 0,
                           0, 0.0001f, 0,
                           0, 0, 0.0001f);
       Vector3F v = Vector3F.One;
       Vector3F w = m * v;
       Assert.IsTrue(Vector3F.AreNumericallyEqual(v, m.Inverse * w));
       Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.Identity, m * m.Inverse));
 }
示例#45
0
 public void Indexer2d()
 {
     Matrix33F m = new Matrix33F(rowMajor, MatrixOrder.RowMajor);
       for (int column = 0; column < 3; column++)
     for (int row = 0; row < 3; row++)
       Assert.AreEqual(columnMajor[column * 3 + row], m[row, column]);
       m = Matrix33F.Zero;
       for (int column = 0; column < 3; column++)
     for (int row = 0; row < 3; row++)
       m[row, column] = (float) (row * 3 + column + 1);
       Assert.AreEqual(new Matrix33F(rowMajor, MatrixOrder.RowMajor), m);
 }
示例#46
0
 public void Indexer1dException4()
 {
     Matrix33F m = new Matrix33F();
       float x = m[9];
 }
示例#47
0
 public void Indexer1dException2()
 {
     Matrix33F m = new Matrix33F();
       m[9] = 0.0f;
 }
示例#48
0
        public void Indexer1d()
        {
            Matrix33F m = new Matrix33F(rowMajor, MatrixOrder.RowMajor);
              for (int i = 0; i < 9; i++)
            Assert.AreEqual(rowMajor[i], m[i]);

              m = Matrix33F.Zero;
              for (int i = 0; i < 9; i++)
            m[i] = rowMajor[i];
              Assert.AreEqual(new Matrix33F(rowMajor, MatrixOrder.RowMajor), m);
        }
示例#49
0
 public void ImplicitMatrix33DCast()
 {
     float m00 = 23.5f; float m01 = 0.0f; float m02 = -11.0f;
       float m10 = 33.5f; float m11 = 1.1f; float m12 = -12.0f;
       float m20 = 43.5f; float m21 = 2.2f; float m22 = -13.0f;
       Matrix33D matrix33D = new Matrix33F(m00, m01, m02, m10, m11, m12, m20, m21, m22);
       Assert.IsTrue(Numeric.AreEqual(m00, (float)matrix33D[0, 0]));
       Assert.IsTrue(Numeric.AreEqual(m01, (float)matrix33D[0, 1]));
       Assert.IsTrue(Numeric.AreEqual(m02, (float)matrix33D[0, 2]));
       Assert.IsTrue(Numeric.AreEqual(m10, (float)matrix33D[1, 0]));
       Assert.IsTrue(Numeric.AreEqual(m11, (float)matrix33D[1, 1]));
       Assert.IsTrue(Numeric.AreEqual(m12, (float)matrix33D[1, 2]));
       Assert.IsTrue(Numeric.AreEqual(m20, (float)matrix33D[2, 0]));
       Assert.IsTrue(Numeric.AreEqual(m21, (float)matrix33D[2, 1]));
       Assert.IsTrue(Numeric.AreEqual(m22, (float)matrix33D[2, 2]));
 }
示例#50
0
        public void MultiplyVectorOperator()
        {
            Vector3F v = new Vector3F(2.34f, 3.45f, 4.56f);
              Assert.AreEqual(v, Matrix33F.Identity * v);
              Assert.AreEqual(Vector3F.Zero, Matrix33F.Zero * v);

              Matrix33F m = new Matrix33F(12, 23, 45,
                                67, 89, 90,
                                43, 65, 87);
              Assert.IsTrue(Vector3F.AreNumericallyEqual(v, m * m.Inverse * v));

              for (int i = 0; i < 3; i++)
            Assert.AreEqual(Vector3F.Dot(m.GetRow(i), v), (m * v)[i]);
        }
示例#51
0
 public void NegationOperator()
 {
     Matrix33F m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
       for (int i = 0; i < 9; i++)
     Assert.AreEqual(-rowMajor[i], (-m)[i]);
 }
示例#52
0
        public void Invert()
        {
            Assert.AreEqual(Matrix33F.Identity, Matrix33F.Identity.Inverse);

              Matrix33F m = new Matrix33F(1, 2, 3,
                                  2, 5, 8,
                                  7, 6, -1);
              Vector3F v = Vector3F.One;
              Vector3F w = m * v;
              Matrix33F im = m;
              im.Invert();
              Assert.IsTrue(Vector3F.AreNumericallyEqual(v, im * w));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.Identity, m * im));
        }
示例#53
0
        public void SerializationBinary()
        {
            Matrix33F m1 = new Matrix33F(12, 23, 45,
                                   56, 67, 89,
                                   90, 12, 43.3f);
              Matrix33F m2;

              string fileName = "SerializationMatrix33F.bin";

              if (File.Exists(fileName))
            File.Delete(fileName);

              FileStream fs = new FileStream(fileName, FileMode.Create);

              BinaryFormatter formatter = new BinaryFormatter();
              formatter.Serialize(fs, m1);
              fs.Close();

              fs = new FileStream(fileName, FileMode.Open);
              formatter = new BinaryFormatter();
              m2 = (Matrix33F) formatter.Deserialize(fs);
              fs.Close();

              Assert.AreEqual(m1, m2);
        }
示例#54
0
 public void InvertException()
 {
     Matrix33F m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
       m.Invert();
 }
示例#55
0
        public void SerializationJson()
        {
            Matrix33F m1 = new Matrix33F(12, 23, 45,
                                   56, 67, 89,
                                   90, 12, 43.3f);
              Matrix33F m2;

              string fileName = "SerializationMatrix33F.json";

              if (File.Exists(fileName))
            File.Delete(fileName);

              var serializer = new DataContractJsonSerializer(typeof(Matrix33F));
              using (var stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write))
            serializer.WriteObject(stream, m1);

              using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            m2 = (Matrix33F)serializer.ReadObject(stream);

              Assert.AreEqual(m1, m2);
        }
示例#56
0
        public void IsNaN()
        {
            const int numberOfRows = 3;
              const int numberOfColumns = 3;
              Assert.IsFalse(new Matrix33F().IsNaN);

              for (int r = 0; r < numberOfRows; r++)
              {
            for (int c = 0; c < numberOfColumns; c++)
            {
              Matrix33F m = new Matrix33F();
              m[r, c] = float.NaN;
              Assert.IsTrue(m.IsNaN);
            }
              }
        }
示例#57
0
        // Computes a bounding box that contains the given points. The bounding box orientation
        // is determined by the given orientation. The outputs are the box extent and the box center.
        // volumeLimit is used for early out.
        // Returns the volume of the new box.
        // If the new box volume is smaller than volumeLimit, the 6 extreme vertices are moved to the
        // front of the list.
        private static float ComputeBoundingBox(IList<Vector3F> points, Matrix33F boxOrientation, float volumeLimit, out Vector3F boxExtent, out Vector3F boxCenter)
        {
            boxExtent = new Vector3F(float.PositiveInfinity);
              boxCenter = Vector3F.Zero;
              float volume = float.PositiveInfinity;

              // The inverse orientation.
              Matrix33F orientationInverse = boxOrientation.Transposed;

              // The min and max points in the local box space.
              Vector3F min = new Vector3F(float.PositiveInfinity);
              Vector3F max = new Vector3F(float.NegativeInfinity);

              // Remember the extreme points.
              Vector3F minX = Vector3F.Zero;
              Vector3F maxX = Vector3F.Zero;
              Vector3F minY = Vector3F.Zero;
              Vector3F maxY = Vector3F.Zero;
              Vector3F minZ = Vector3F.Zero;
              Vector3F maxZ = Vector3F.Zero;

              for (int i = 0; i < points.Count; i++)
              {
            var point = points[i];

            // Rotate point into local box space.
            var localPoint = orientationInverse * point;

            // Is this vertex on the box surface?
            bool isExtreme = false;

            // Store min and max coordinates.
            if (localPoint.X < min.X)
            {
              min.X = localPoint.X;
              minX = point;
              isExtreme = true;
            }

            if (localPoint.X > max.X)
            {
              max.X = localPoint.X;
              maxX = point;
              isExtreme = true;
            }

            if (localPoint.Y < min.Y)
            {
              min.Y = localPoint.Y;
              minY = point;
              isExtreme = true;
            }

            if (localPoint.Y > max.Y)
            {
              max.Y = localPoint.Y;
              maxY = point;
              isExtreme = true;
            }

            if (localPoint.Z < min.Z)
            {
              min.Z = localPoint.Z;
              minZ = point;
              isExtreme = true;
            }

            if (localPoint.Z > max.Z)
            {
              max.Z = localPoint.Z;
              maxZ = point;
              isExtreme = true;
            }

            if (isExtreme)
            {
              // The box has grown.
              boxExtent = max - min;
              volume = boxExtent.X * boxExtent.Y * boxExtent.Z;

              // Early out, if volume is beyond the limit.
              if (volume > volumeLimit)
            return float.PositiveInfinity;
            }
              }

              // If we come to here, the new box is better than the old known box.
              // Move the extreme vertices to the front of the list. This improves
              // the early out drastically. - See Real-Time Collision Detection.
              points.Remove(minX);
              points.Insert(0, minX);
              points.Remove(minY);
              points.Insert(0, minY);
              points.Remove(minZ);
              points.Insert(0, minZ);
              points.Remove(maxX);
              points.Insert(0, maxX);
              points.Remove(maxY);
              points.Insert(0, maxY);
              points.Remove(maxZ);
              points.Insert(0, maxZ);

              // Compute center and convert it to world space.
              Vector3F localCenter = (min + max) / 2;
              boxCenter = boxOrientation * localCenter;

              return volume;
        }
示例#58
0
        public void IsSymmetric()
        {
            Matrix33F m = new Matrix33F(new float[3, 3] { { 1, 2, 3 },
                                                    { 2, 4, 5 },
                                                    { 3, 5, 7 } });
              Assert.AreEqual(true, m.IsSymmetric);

              m = new Matrix33F(new float[3, 3] { { 1, 2, 3 },
                                          { 4, 5, 2 },
                                          { 7, 4, 1 } });
              Assert.AreEqual(false, m.IsSymmetric);
        }
示例#59
0
 /// <summary>
 /// Gets the intersection point of three planes.
 /// </summary>
 /// <param name="planeA">The first plane.</param>
 /// <param name="planeB">The second plane.</param>
 /// <param name="planeC">The third plane.</param>
 /// <returns>
 /// The point that touches all three planes. (<see cref="float.NaN"/>, <see cref="float.NaN"/>, 
 /// <see cref="float.NaN"/>) is returned if there is no unique intersection point, for example,
 /// when two planes are parallel or the planes intersect in a line.
 /// </returns>
 public static Vector3F GetIntersection(Plane planeA, Plane planeB, Plane planeC)
 {
     // Get a point that meets this requirements: Dot(plane.Normal, point) == plane.DistanceFromOrigin
       Matrix33F matrix = new Matrix33F(planeA.Normal.X, planeA.Normal.Y, planeA.Normal.Z,
                                planeB.Normal.X, planeB.Normal.Y, planeB.Normal.Z,
                                planeC.Normal.X, planeC.Normal.Y, planeC.Normal.Z);
       Vector3F distances = new Vector3F(planeA.DistanceFromOrigin, planeB.DistanceFromOrigin, planeC.DistanceFromOrigin);
       bool isInvertible = matrix.TryInvert();
       if (isInvertible)
     return matrix * distances;
       else
     return new Vector3F(float.NaN);
 }
示例#60
0
 public void Multiplication()
 {
     float s = 0.1234f;
       Matrix33F m = new Matrix33F(columnMajor, MatrixOrder.ColumnMajor);
       m = Matrix33F.Multiply(s, m);
       for (int i = 0; i < 9; i++)
     Assert.AreEqual(rowMajor[i] * s, m[i]);
 }