コード例 #1
0
        private void SynchronizeShape()
        {
            Debug.Assert(ParticleSystem != null);

            // Note: Scene does not allow TransformedShapes with infinite shapes.
            // --> Handle infinite shapes explicitly. (The code below only checks for InfiniteShape.
            // LineShape or PlaneShape will raise an exception in Scene!)

            if (ParticleSystem.ReferenceFrame == ParticleReferenceFrame.Local || ParticleSystem.Shape is InfiniteShape)
            {
                Shape = ParticleSystem.Shape;
            }
            else
            {
                // Particles are simulated in world space. ParticleSystem.Shape must not be scale by
                // SceneNode.ScaleWorld. --> Add a TransformedShape that negates the scale.
                var transformedShape = Shape as TransformedShape;
                if (transformedShape == null)
                {
                    transformedShape = new TransformedShape(new GeometricObject());
                    Shape            = transformedShape;
                }

                var geometricObject = transformedShape.Child as GeometricObject;
                if (geometricObject == null)
                {
                    geometricObject        = new GeometricObject();
                    transformedShape.Child = geometricObject;
                }

                geometricObject.Shape = ParticleSystem.Shape;
                geometricObject.Scale = Vector3F.One / ScaleWorld;
            }
        }
コード例 #2
0
        public void GetAxisAlignedBoundingBox()
        {
            Assert.AreEqual(new Aabb(new Vector3(0, -100, 0), new Vector3(1000, 0, 1000)),
                            new HeightField().GetAabb(Pose.Identity));
            Assert.AreEqual(new Aabb(new Vector3(1000, -101, 2000), new Vector3(1100, 5, 2200)),
                            _field.GetAabb(Pose.Identity));
            Assert.AreEqual(new Aabb(new Vector3(0, -1, 0), new Vector3(10, 5, 20)),
                            new HeightField(0, 0, 10, 20, _samples, 3, 8)
            {
                Depth = 0
            }.GetAabb(Pose.Identity));

            // Now with pose.
            Quaternion rotation = Quaternion.CreateRotationX(0.2f);
            Pose       pose     = new Pose(new Vector3(1, 1, 1), rotation);

            _field.Depth = 0;
            var box = new TransformedShape(
                new GeometricObject(new BoxShape(100, 6, 200), new Pose(new Vector3(1050, 2, 2100))));

            Assert.IsTrue(Vector3.AreNumericallyEqual(box.GetAabb(pose).Minimum, _field.GetAabb(pose).Minimum));
            _field.Depth = 4;
            box          = new TransformedShape(
                new GeometricObject(new BoxShape(100, 10, 200), new Pose(new Vector3(1000, 0, 2000))));
            Assert.IsTrue(Vector3.AreNumericallyEqual(box.GetAabb(pose).Minimum + rotation.Rotate(new Vector3(50, 0, 100)), _field.GetAabb(pose).Minimum));
        }
コード例 #3
0
        private static CompoundShape create_shapes(RepeatedField <Collider> colliders)
        {
            if (colliders == null || colliders.Count == 0)
            {
                throw new Exception("Colliders is null or count is zero");
            }

            var shape_buffer = new List <TransformedShape>();

            foreach (var collider in colliders)
            {
                Shape      shape = null;
                Vector3    center;
                Quaternion rotation;

                switch (collider.ShapeCase)
                {
                case Collider.ShapeOneofCase.None:
                    throw new Exception("Collider without any shape");

                case Collider.ShapeOneofCase.Box:
                    var box = collider.Box;
                    shape    = new Jitter.Collision.Shapes.BoxShape(box.Length, box.Height, box.Width);
                    center   = box.Center;
                    rotation = box.Rotation;
                    break;

                case Collider.ShapeOneofCase.Sphere:
                    var sphere = collider.Sphere;
                    shape    = new Jitter.Collision.Shapes.SphereShape(sphere.Radius);
                    center   = sphere.Center;
                    rotation = sphere.Rotation;
                    break;

                case Collider.ShapeOneofCase.Capsule:
                    var capsule = collider.Capsule;
                    shape    = new Jitter.Collision.Shapes.CapsuleShape(capsule.Height, capsule.Radius);
                    center   = capsule.Center;
                    rotation = capsule.Rotation;
                    break;

                default:
                    Debug.Assert(false, "Unhandled enum value " + collider.ShapeCase);
                    throw new Exception();
                }

                var center_j          = to_j(center);
                var rotation_j        = to_j(rotation);
                var transformed_shape = new TransformedShape(shape, JMatrix.Identity, center_j);
                shape_buffer.Add(transformed_shape);

                if (collider.Children != null && collider.Children.Count > 0)
                {
                    create_shapes(collider.Children);
                }
            }

            return(new CompoundShape(shape_buffer));
        }
コード例 #4
0
ファイル: MassTest.cs プロジェクト: terrynoya/DigitalRune
        public void TransformedShapeNonuniformScaleWithRotationNotSupported()
        {
            var       s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3F(0.7f, 0.8f, 0.9f), new Pose(new Vector3F(-1, 7, 4), QuaternionF.CreateRotationX(1))));
            float     m0;
            Vector3F  com0;
            Matrix33F i0;

            MassHelper.GetMass(s, new Vector3F(2, 2.1f, 2.8f), 1, true, 0.001f, 10, out m0, out com0, out i0);
        }
コード例 #5
0
ファイル: MassTest.cs プロジェクト: terrynoya/DigitalRune
        public void TransformedShapeNegativeScalingNotSupported()
        {
            var       s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3F(0.7f, 0.8f, 0.9f), new Pose(new Vector3F(-1, 7, 4))));
            float     m0;
            Vector3F  com0;
            Matrix33F i0;

            MassHelper.GetMass(s, new Vector3F(2, 2.1f, -2.8f), 1, true, 0.001f, 10, out m0, out com0, out i0);
        }
コード例 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FigureRenderData"/> class.
        /// </summary>
        public FigureRenderData()
        {
            BoundingShape = new TransformedShape
            {
                Child = new GeometricObject(new BoxShape(new Vector3(Single.MaxValue)))
            };

            // The HitShape is created on demand.
        }
コード例 #7
0
        //--------------------------------------------------------------
        #region Creation & Cleanup
        //--------------------------------------------------------------

        /// <summary>
        /// Initializes a new instance of the <see cref="Spotlight"/> class.
        /// </summary>
        public Spotlight()
        {
            Color             = Vector3F.One;
            DiffuseIntensity  = 1;
            SpecularIntensity = 1;
            HdrScale          = 1;
            _falloffAngle     = 20.0f * ConstantsF.Pi / 180;
            Shape             = new TransformedShape(new GeometricObject(new ConeShape((float)Math.Tan(MathHelper.ToRadians(30)) * 5, 5), new Pose(new Vector3F(0, 0, -5), QuaternionF.CreateRotationX(ConstantsF.PiOver2))));
            Attenuation       = 2;
        }
コード例 #8
0
        public CompoundShape(TransformedShape[] shapes)
        {
            this.shapes = new TransformedShape[shapes.Length];
            Array.Copy(shapes, this.shapes, shapes.Length);

            if (!TestValidity())
                throw new ArgumentException("Multishapes are not supported!");

            this.UpdateShape();
        }
コード例 #9
0
        private static Shape ComputeAxisAlignedBoundingShape(MeshContent mesh)
        {
            Debug.Assert(mesh.Positions.Count > 0);

            List <Vector3> points = mesh.Positions.Select(position => (Vector3)position).ToList();

            var boundingShape = GeometryHelper.CreateBoundingShape(points);

            // Compute minimal sphere.
            Vector3 center;
            float   radius;

            GeometryHelper.ComputeBoundingSphere(points, out radius, out center);
            SphereShape sphere       = new SphereShape(radius);
            float       sphereVolume = sphere.GetVolume();

            // Compute minimal AABB.
            Aabb aabb = new Aabb(points[0], points[0]);

            for (int i = 1; i < points.Count; i++)
            {
                aabb.Grow(points[i]);
            }
            var   boxPose   = new Pose(aabb.Center);
            var   box       = new BoxShape(aabb.Extent);
            float boxVolume = box.GetVolume();

            // Return the object with the smallest volume.
            // A TransformedShape is used if the shape needs to be translated.
            if (sphereVolume < boxVolume)
            {
                if (center.IsNumericallyZero)
                {
                    boundingShape = sphere;
                }
                else
                {
                    boundingShape = new TransformedShape(new GeometricObject(sphere, new Pose(center)));
                }
            }
            else
            {
                if (!boxPose.HasTranslation)
                {
                    boundingShape = box;
                }
                else
                {
                    boundingShape = new TransformedShape(new GeometricObject(box, boxPose));
                }
            }

            return(boundingShape);
        }
コード例 #10
0
        public void InnerPoint2()
        {
            TransformedShape t = new TransformedShape
            {
                Child = new GeometricObject
                {
                    Pose  = new Pose(new Vector3(0, 1, 0)),
                    Shape = new PointShape(1, 0, 0),
                },
            };

            Assert.AreEqual(new Vector3(1, 1, 0), t.InnerPoint);
        }
コード例 #11
0
        /// <summary>
        /// Gets a bounding shape that matches the specified AABB.
        /// </summary>
        /// <param name="aabb">The AABB.</param>
        /// <returns>A box or transformed box that matches the specified AABB.</returns>
        private Shape GetBoundingShape(Aabb aabb)
        {
            // The AABB of the LOD is real world size including scaling. We have to undo
            // the scale because this LodGroupNode also applies the same scale.
            var unscaledCenter = aabb.Center / ScaleWorld;
            var unscaledExtent = aabb.Extent / ScaleWorld;

            // Get existing shape objects to avoid unnecessary memory allocation.
            BoxShape         boxShape;
            GeometricObject  geometricObject  = null;
            TransformedShape transformedShape = null;

            if (Shape is BoxShape)
            {
                boxShape = (BoxShape)Shape;
            }
            else if (Shape is TransformedShape)
            {
                transformedShape = (TransformedShape)Shape;
                geometricObject  = (GeometricObject)transformedShape.Child;
                boxShape         = (BoxShape)geometricObject.Shape;
            }
            else
            {
                boxShape = new BoxShape();
            }

            // Make bounding box the size of the unscaled AABB.
            boxShape.Extent = unscaledExtent;

            if (unscaledCenter.IsNumericallyZero)
            {
                // Bounding box is centered at origin.
                return(boxShape);
            }

            // Apply offset to bounding box.
            if (transformedShape == null)
            {
                geometricObject  = new GeometricObject(boxShape, new Pose(unscaledCenter));
                transformedShape = new TransformedShape(geometricObject);
            }
            else
            {
                geometricObject.Shape = boxShape;
                geometricObject.Pose  = new Pose(unscaledCenter);
            }

            return(transformedShape);
        }
コード例 #12
0
        public void TransformedShapeTest()
        {
            var c = new TransformedShape();

            Assert.AreEqual(0, c.GetVolume(0.1f, 10));

            c.Child = new GeometricObject(
                new BoxShape(1, 2, 3),
                new Vector3(10, 10, 10),
                new Pose(new Vector3(1, 2, 3), RandomHelper.Random.NextQuaternion()));

            var v0 = c.GetVolume(0.001f, 10);

            Assert.AreEqual(10 * 20 * 30, v0);
        }
コード例 #13
0
ファイル: ProxyNode.cs プロジェクト: terrynoya/DigitalRune
        /// <summary>
        /// Gets a bounding shape that matches the specified AABB.
        /// </summary>
        /// <param name="aabb">The AABB.</param>
        /// <returns>A box or transformed box that matches the specified AABB.</returns>
        private Shape GetBoundingShape(Aabb aabb)
        {
            // Get existing shape objects to avoid unnecessary memory allocation.
            BoxShape         boxShape;
            GeometricObject  geometricObject  = null;
            TransformedShape transformedShape = null;

            if (Shape is BoxShape)
            {
                boxShape = (BoxShape)Shape;
            }
            else if (Shape is TransformedShape)
            {
                transformedShape = (TransformedShape)Shape;
                geometricObject  = (GeometricObject)transformedShape.Child;
                boxShape         = (BoxShape)geometricObject.Shape;
            }
            else
            {
                boxShape = new BoxShape();
            }

            // Make box the size of the AABB.
            boxShape.Extent = aabb.Extent;

            if (aabb.Center.IsNumericallyZero)
            {
                // Bounding box is centered at origin.
                return(boxShape);
            }

            // Apply offset to bounding box.
            if (transformedShape == null)
            {
                geometricObject  = new GeometricObject(boxShape, new Pose(aabb.Center));
                transformedShape = new TransformedShape(geometricObject);
            }
            else
            {
                geometricObject.Shape = boxShape;
                geometricObject.Pose  = new Pose(aabb.Center);
            }

            return(transformedShape);
        }
コード例 #14
0
        public void SerializationBinary()
        {
            Pose       pose       = new Pose(new Vector3(1, 2, 3));
            PointShape pointShape = new PointShape(3, 4, 5);
            var        a          = new TransformedShape(new GeometricObject(pointShape, pose));

            // Serialize object.
            var stream    = new MemoryStream();
            var formatter = new BinaryFormatter();

            formatter.Serialize(stream, a);

            // Deserialize object.
            stream.Position = 0;
            var deserializer = new BinaryFormatter();
            var b            = (TransformedShape)deserializer.Deserialize(stream);

            Assert.AreEqual(a.Child.Pose, b.Child.Pose);
            Assert.AreEqual(((PointShape)a.Child.Shape).Position, ((PointShape)b.Child.Shape).Position);
        }
コード例 #15
0
        public void Clone()
        {
            Pose pose = new Pose(new Vector3F(1, 2, 3));
              PointShape pointShape = new PointShape(3, 4, 5);
              GeometricObject geometry = new GeometricObject(pointShape, pose);

              TransformedShape transformedShape = new TransformedShape(geometry);
              TransformedShape clone = transformedShape.Clone() as TransformedShape;
              Assert.IsNotNull(clone);
              Assert.IsNotNull(clone.Child);
              Assert.AreNotSame(geometry, clone.Child);
              Assert.IsTrue(clone.Child is GeometricObject);
              Assert.AreEqual(pose, clone.Child.Pose);
              Assert.IsNotNull(clone.Child.Shape);
              Assert.AreNotSame(pointShape, clone.Child.Shape);
              Assert.IsTrue(clone.Child.Shape is PointShape);
              Assert.AreEqual(pointShape.Position, ((PointShape)clone.Child.Shape).Position);
              Assert.AreEqual(transformedShape.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum);
              Assert.AreEqual(transformedShape.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum);
        }
コード例 #16
0
        public void GetAabb()
        {
            Assert.AreEqual(new Vector3(0, 0, 0), new TransformedShape().GetAabb(Pose.Identity).Minimum);
            Assert.AreEqual(new Vector3(0, 0, 0), new TransformedShape().GetAabb(Pose.Identity).Maximum);

            TransformedShape t = new TransformedShape
            {
                Child = new GeometricObject
                {
                    Pose  = new Pose(new Vector3(0, 1, 0)),
                    Shape = new SphereShape(10),
                },
            };

            Assert.AreEqual(new Vector3(-10, -9, -10), t.GetAabb(Pose.Identity).Minimum);
            Assert.AreEqual(new Vector3(10, 11, 10), t.GetAabb(Pose.Identity).Maximum);

            Assert.AreEqual(new Vector3(-8, -9, -10), t.GetAabb(new Pose(new Vector3(2, 0, 0))).Minimum);
            Assert.AreEqual(new Vector3(12, 11, 10), t.GetAabb(new Pose(new Vector3(2, 0, 0))).Maximum);
        }
コード例 #17
0
        public void GetAabb()
        {
            Assert.AreEqual(new Vector3F(0, 0, 0), new TransformedShape().GetAabb(Pose.Identity).Minimum);
              Assert.AreEqual(new Vector3F(0, 0, 0), new TransformedShape().GetAabb(Pose.Identity).Maximum);

              TransformedShape t = new TransformedShape
              {
            Child = new GeometricObject
            {
              Pose = new Pose(new Vector3F(0, 1, 0)),
              Shape = new SphereShape(10),
            },
              };

              Assert.AreEqual(new Vector3F(-10, -9, -10), t.GetAabb(Pose.Identity).Minimum);
              Assert.AreEqual(new Vector3F(10, 11, 10), t.GetAabb(Pose.Identity).Maximum);

              Assert.AreEqual(new Vector3F(-8, -9, -10), t.GetAabb(new Pose(new Vector3F(2, 0, 0))).Minimum);
              Assert.AreEqual(new Vector3F(12, 11, 10), t.GetAabb(new Pose(new Vector3F(2, 0, 0))).Maximum);
        }
コード例 #18
0
        public void Clone()
        {
            Pose            pose       = new Pose(new Vector3(1, 2, 3));
            PointShape      pointShape = new PointShape(3, 4, 5);
            GeometricObject geometry   = new GeometricObject(pointShape, pose);

            TransformedShape transformedShape = new TransformedShape(geometry);
            TransformedShape clone            = transformedShape.Clone() as TransformedShape;

            Assert.IsNotNull(clone);
            Assert.IsNotNull(clone.Child);
            Assert.AreNotSame(geometry, clone.Child);
            Assert.IsTrue(clone.Child is GeometricObject);
            Assert.AreEqual(pose, clone.Child.Pose);
            Assert.IsNotNull(clone.Child.Shape);
            Assert.AreNotSame(pointShape, clone.Child.Shape);
            Assert.IsTrue(clone.Child.Shape is PointShape);
            Assert.AreEqual(pointShape.Position, ((PointShape)clone.Child.Shape).Position);
            Assert.AreEqual(transformedShape.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum);
            Assert.AreEqual(transformedShape.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum);
        }
コード例 #19
0
        public void GetAxisAlignedBoundingBox()
        {
            Assert.AreEqual(new Aabb(new Vector3F(0, -100, 0), new Vector3F(1000, 0, 1000)),
                      new HeightField().GetAabb(Pose.Identity));
              Assert.AreEqual(new Aabb(new Vector3F(1000, -101, 2000), new Vector3F(1100, 5, 2200)),
                      _field.GetAabb(Pose.Identity));
              Assert.AreEqual(new Aabb(new Vector3F(0, -1, 0), new Vector3F(10, 5, 20)),
                      new HeightField(0, 0, 10, 20, _samples, 3, 8) { Depth = 0 }.GetAabb(Pose.Identity));

              // Now with pose.
              QuaternionF rotation = QuaternionF.CreateRotationX(0.2f);
              Pose pose = new Pose(new Vector3F(1, 1, 1), rotation);
              _field.Depth = 0;
              var box = new TransformedShape(
            new GeometricObject(new BoxShape(100, 6, 200), new Pose(new Vector3F(1050, 2, 2100))));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(box.GetAabb(pose).Minimum, _field.GetAabb(pose).Minimum));
              _field.Depth = 4;
              box = new TransformedShape(
            new GeometricObject(new BoxShape(100, 10, 200), new Pose(new Vector3F(1000, 0, 2000))));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(box.GetAabb(pose).Minimum + rotation.Rotate(new Vector3F(50, 0, 100)), _field.GetAabb(pose).Minimum));
        }
コード例 #20
0
ファイル: MassTest.cs プロジェクト: terrynoya/DigitalRune
        public void ApproximateAabbMass()
        {
            var       s = new ConvexHullOfPoints(new[] { new Vector3F(1, 1, 1), new Vector3F(2, 4, 6) });
            float     m0;
            Vector3F  com0;
            Matrix33F i0;

            MassHelper.GetMass(s, new Vector3F(1.2f, 2.1f, 0.6f), 0.7f, true, 0.001f, 0, out m0, out com0, out i0);

            var       s2 = new TransformedShape(new GeometricObject(new BoxShape(1, 3, 5), new Pose(new Vector3F(1.5f, 2.5f, 3.5f))));
            float     m1;
            Vector3F  com1;
            Matrix33F i1;

            MassHelper.GetMass(s2, new Vector3F(1.2f, 2.1f, 0.6f), 0.7f, true, 0.001f, 0, out m1, out com1, out i1);

            const float e = 0.0001f;

            Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
            Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
コード例 #21
0
        public void PropertyChangedTest()
        {
            TransformedShape t = new TransformedShape();

            t.Changed += delegate { _propertyChanged = true; };

            Assert.IsFalse(_propertyChanged);

            ((GeometricObject)t.Child).Shape = new SphereShape(1);
            Assert.IsTrue(_propertyChanged);
            _propertyChanged = false;

            ((SphereShape)t.Child.Shape).Radius = 3;
            Assert.IsTrue(_propertyChanged);
            _propertyChanged = false;

            ((GeometricObject)t.Child).Pose = new Pose(new Vector3(1, 2, 3));
            Assert.IsTrue(_propertyChanged);
            _propertyChanged = false;

            // Setting Pose to the same value does not create a changed event.
            ((GeometricObject)t.Child).Pose = new Pose(new Vector3(1, 2, 3));
            Assert.IsFalse(_propertyChanged);
            _propertyChanged = false;

            ((GeometricObject)t.Child).Pose = Pose.Identity;
            Assert.IsTrue(_propertyChanged);
            _propertyChanged = false;

            t.Child = new GeometricObject();
            Assert.IsTrue(_propertyChanged);
            _propertyChanged = false;

            // Setting Pose to the same value does not create a changed event.
            ((GeometricObject)t.Child).Pose = Pose.Identity;
            Assert.IsFalse(_propertyChanged);
            _propertyChanged = false;
        }
コード例 #22
0
        private Shape BuildBoundingShape(DRMeshNodeContent meshNode)
        {
            Shape boundingShape = Shape.Empty;

            var mesh = meshNode.InputMesh;

            if (mesh.Positions.Count > 0)
            {
                if (_modelDescription != null && _modelDescription.AabbEnabled)
                {
                    // We assume that the AABB is given in the local space.
                    Vector3 aabbMinimum = (Vector3)_modelDescription.AabbMinimum;
                    Vector3 aabbMaximum = (Vector3)_modelDescription.AabbMaximum;
                    Vector3 center      = (aabbMaximum + aabbMinimum) / 2;
                    Vector3 extent      = aabbMaximum - aabbMinimum;
                    if (center.IsNumericallyZero)
                    {
                        boundingShape = new BoxShape(extent);
                    }
                    else
                    {
                        boundingShape = new TransformedShape(new GeometricObject(new BoxShape(extent), new Pose(center)));
                    }
                }
                else
                {
                    // Best fit bounding shape.
                    //boundingShape = ComputeBestFitBoundingShape(mesh);

                    // Non-rotated bounding shape. This is usually larger but contains no rotations.
                    // (TransformedShapes with rotated children cannot be used with non-uniform scaling.)
                    boundingShape = ComputeAxisAlignedBoundingShape(mesh);
                }
            }

            return(boundingShape);
        }
コード例 #23
0
ファイル: MassTest.cs プロジェクト: DireAussie/MinimalRune
        public void TransformedShapeMassWithScaling()
        {
            var     s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3(0.7f), new Pose(new Vector3(-1, 7, 4), RandomHelper.Random.NextQuaternion())));
            float   m0;
            Vector3 com0;
            Matrix  i0;

            MassHelper.GetMass(s, new Vector3(2), 1, true, 0.001f, 10, out m0, out com0, out i0);

            var m = s.GetMesh(0.001f, 6);

            m.Transform(Matrix.CreateScale(2));
            float   m1;
            Vector3 com1;
            Matrix  i1;

            MassHelper.GetMass(m, out m1, out com1, out i1);

            const float e = 0.01f;

            Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
            Assert.IsTrue(Vector3.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
            Assert.IsTrue(Matrix.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
コード例 #24
0
ファイル: MassTest.cs プロジェクト: terrynoya/DigitalRune
        public void TransformedShapeMassWithNonuniformScaling()
        {
            var       s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3F(0.7f, 0.8f, 0.9f), new Pose(new Vector3F(-1, 7, 4))));
            float     m0;
            Vector3F  com0;
            Matrix33F i0;

            MassHelper.GetMass(s, new Vector3F(2, 2.1f, 2.8f), 1, true, 0.001f, 10, out m0, out com0, out i0);

            var m = s.GetMesh(0.001f, 6);

            m.Transform(Matrix44F.CreateScale(2, 2.1f, 2.8f));
            float     m1;
            Vector3F  com1;
            Matrix33F i1;

            MassHelper.GetMass(m, out m1, out com1, out i1);

            const float e = 0.01f;

            Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
            Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
コード例 #25
0
        public IntersectionSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService)
            {
                RenderCallback = Render,
            };

            GraphicsService.Screens.Insert(0, delegateGraphicsScreen);

            // Add a custom game object which controls the camera.
            _cameraObject = new CameraObject(Services, 10);
            _cameraObject.ResetPose(new Vector3(0, 0, -4), ConstantsF.Pi, 0);
            GameObjectService.Objects.Add(_cameraObject);

            // Create a new scene with some lights.
            _scene = new Scene();
            SceneSample.InitializeDefaultXnaLights(_scene);

            _meshRenderer  = new MeshRenderer();
            _debugRenderer = new DebugRenderer(GraphicsService, null);

            _intersectionRenderer = new IntersectionRenderer(GraphicsService, ContentManager)
            {
                DownsampleFactor = 1,
            };

            //_submeshA = MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new SphereShape(0.5f).GetMesh(0.001f, 5), MathHelper.ToRadians(70));
            //_submeshB = MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new BoxShape(1, 1, 2).GetMesh(0.001f, 5), MathHelper.ToRadians(70));

            var meshNodeA = CreateMeshNode(new[]
            {
                MeshHelper.CreateTorus(GraphicsService.GraphicsDevice, 1, 0.3f, 30),
                MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new BoxShape(1, 1, 2).GetMesh(0.001f, 5), MathHelper.ToRadians(70)),
            },
                                           Color.DarkBlue);

            meshNodeA.PoseWorld = new Pose(RandomHelper.Random.NextVector3(-0.5f, 0.5f),
                                           RandomHelper.Random.NextQuaternion());
            _scene.Children.Add(meshNodeA);
            _debugRenderer.DrawObject(meshNodeA, Color.Green, true, false);

            var shape = new TransformedShape(
                new GeometricObject(new SphereShape(0.5f), new Pose(new Vector3(1, 0, 0))));
            var meshNodeB = CreateMeshNode(new[]
            {
                MeshHelper.CreateTorus(GraphicsService.GraphicsDevice, 1, 0.3f, 30),
                MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, shape.GetMesh(0.001f, 4), MathHelper.ToRadians(90)),
            },
                                           Color.Gray);

            meshNodeB.PoseWorld = new Pose(RandomHelper.Random.NextVector3(-1f, 1f),
                                           RandomHelper.Random.NextQuaternion());
            _scene.Children.Add(meshNodeB);
            _debugRenderer.DrawObject(meshNodeB, Color.Green, true, false);

            var meshNodeC = CreateMeshNode(new[]
            {
                MeshHelper.CreateBox(GraphicsService.GraphicsDevice),
                MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new BoxShape(1, 1, 2).GetMesh(0.001f, 5), MathHelper.ToRadians(70))
            },
                                           Color.DarkGreen);

            meshNodeC.PoseWorld = new Pose(RandomHelper.Random.NextVector3(-1f, 1f),
                                           RandomHelper.Random.NextQuaternion());
            meshNodeC.ScaleLocal = new Vector3(0.1f, 1f, 0.5f);
            _scene.Children.Add(meshNodeC);
            _debugRenderer.DrawObject(meshNodeC, Color.Green, true, false);

            _meshNodePairs.Add(new Pair <MeshNode>(meshNodeA, meshNodeB));
            _meshNodePairs.Add(new Pair <MeshNode>(meshNodeA, meshNodeC));
            _meshNodePairs.Add(new Pair <MeshNode>(meshNodeB, meshNodeC));

            CreateGuiControls();
        }
コード例 #26
0
    // Creates a lot of random objects.
    private void CreateRandomObjects()
    {
      var random = new Random();

      var isFirstHeightField = true;

      int currentShape = 0;
      int numberOfObjects = 0;
      while (true)
      {
        numberOfObjects++;
        if (numberOfObjects > ObjectsPerType)
        {
          currentShape++;
          numberOfObjects = 0;
        }

        Shape shape;
        switch (currentShape)
        {
          case 0:
            // Box
            shape = new BoxShape(ObjectSize, ObjectSize * 2, ObjectSize * 3);
            break;
          case 1:
            // Capsule
            shape = new CapsuleShape(0.3f * ObjectSize, 2 * ObjectSize);
            break;
          case 2:
            // Cone
            shape = new ConeShape(1 * ObjectSize, 2 * ObjectSize);
            break;
          case 3:
            // Cylinder
            shape = new CylinderShape(0.4f * ObjectSize, 2 * ObjectSize);
            break;
          case 4:
            // Sphere
            shape = new SphereShape(ObjectSize);
            break;
          case 5:
            // Convex hull of several points.
            ConvexHullOfPoints hull = new ConvexHullOfPoints();
            hull.Points.Add(new Vector3(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize));
            hull.Points.Add(new Vector3(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize));
            hull.Points.Add(new Vector3(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize));
            hull.Points.Add(new Vector3(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize));
            hull.Points.Add(new Vector3(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize));
            shape = hull;
            break;
          case 6:
            // A composite shape: two boxes that form a "T" shape.
            var composite = new CompositeShape();
            composite.Children.Add(
              new GeometricObject(
                new BoxShape(ObjectSize, 3 * ObjectSize, ObjectSize),
                new Pose(new Vector3(0, 0, 0))));
            composite.Children.Add(
              new GeometricObject(
                new BoxShape(2 * ObjectSize, ObjectSize, ObjectSize),
                new Pose(new Vector3(0, 2 * ObjectSize, 0))));
            shape = composite;
            break;
          case 7:
            shape = new CircleShape(ObjectSize);
            break;
          case 8:
            {
              var compBvh = new CompositeShape();
              compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3(0, 0.5f, 0), Matrix.Identity)));
              compBvh.Children.Add(new GeometricObject(new BoxShape(0.8f, 0.5f, 0.5f), new Pose(new Vector3(0.5f, 0.7f, 0), Matrix.CreateRotationZ(-MathHelper.ToRadians(15)))));
              compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3(0, 1.15f, 0), Matrix.Identity)));
              compBvh.Children.Add(new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3(0.6f, 1.15f, 0), Matrix.CreateRotationX(0.3f))));
              compBvh.Partition = new AabbTree<int>();
              shape = compBvh;
              break;
            }
          case 9:
            CompositeShape comp = new CompositeShape();
            comp.Children.Add(new GeometricObject(new BoxShape(0.5f * ObjectSize, 1 * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3(0, 0.5f * ObjectSize, 0), Quaternion.Identity)));
            comp.Children.Add(new GeometricObject(new BoxShape(0.8f * ObjectSize, 0.5f * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3(0.3f * ObjectSize, 0.7f * ObjectSize, 0), Quaternion.CreateRotationZ(-MathHelper.ToRadians(45)))));
            comp.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3(0, 1.15f * ObjectSize, 0), Quaternion.Identity)));
            shape = comp;
            break;
          case 10:
            shape = new ConvexHullOfPoints(new[]
            {
              new Vector3(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize),
              new Vector3(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize),
              new Vector3(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize)
            });
            break;
          case 11:
            ConvexHullOfShapes shapeHull = new ConvexHullOfShapes();
            shapeHull.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3(0, 2 * ObjectSize, 0), Matrix.Identity)));
            shapeHull.Children.Add(new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize), Pose.Identity));
            shape = shapeHull;
            break;
          case 12:
            shape = Shape.Empty;
            break;
          case 13:
            var numberOfSamplesX = 10;
            var numberOfSamplesZ = 10;
            var samples = new float[numberOfSamplesX * numberOfSamplesZ];
            for (int z = 0; z < numberOfSamplesZ; z++)
              for (int x = 0; x < numberOfSamplesX; x++)
                samples[z * numberOfSamplesX + x] = (float)(Math.Cos(z / 3f) * Math.Sin(x / 2f) * BoxSize / 6);
            HeightField heightField = new HeightField(0, 0, 2 * BoxSize, 2 * BoxSize, samples, numberOfSamplesX, numberOfSamplesZ);
            shape = heightField;
            break;
          //case 14:
          //shape = new LineShape(new Vector3(0.1f, 0.2f, 0.3f), new Vector3(0.1f, 0.2f, -0.3f).Normalized);
          //break;            
          case 15:
            shape = new LineSegmentShape(
              new Vector3(0.1f, 0.2f, 0.3f), new Vector3(0.1f, 0.2f, 0.3f) + 3 * ObjectSize * new Vector3(0.1f, 0.2f, -0.3f));
            break;
          case 16:
            shape = new MinkowskiDifferenceShape
            {
              ObjectA = new GeometricObject(new SphereShape(0.1f * ObjectSize)),
              ObjectB = new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize))
            };
            break;
          case 17:
            shape = new MinkowskiSumShape
            {
              ObjectA = new GeometricObject(new SphereShape(0.1f * ObjectSize)),
              ObjectB = new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize)),
            };
            break;
          case 18:
            shape = new OrthographicViewVolume(0, ObjectSize, 0, ObjectSize, ObjectSize / 2, ObjectSize * 2);
            break;
          case 19:
            shape = new PerspectiveViewVolume(MathHelper.ToRadians(60f), 16f / 10, ObjectSize / 2, ObjectSize * 3);
            break;
          case 20:
            shape = new PointShape(0.1f, 0.3f, 0.2f);
            break;
          case 21:
            shape = new RayShape(new Vector3(0.2f, 0, -0.12f), new Vector3(1, 2, 3).Normalized, ObjectSize * 2);
            break;
          case 22:
            shape = new RayShape(new Vector3(0.2f, 0, -0.12f), new Vector3(1, 2, 3).Normalized, ObjectSize * 2)
            {
              StopsAtFirstHit = true
            };
            break;
          case 23:
            shape = new RectangleShape(ObjectSize, ObjectSize * 2);
            break;
          case 24:
            shape = new TransformedShape(
              new GeometricObject(
                new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize),
                new Pose(new Vector3(0.1f, 1, -0.2f))));
            break;
          case 25:
            shape = new TriangleShape(
              new Vector3(ObjectSize, 0, 0), new Vector3(0, ObjectSize, 0), new Vector3(ObjectSize, ObjectSize, ObjectSize));
            break;
          //case 26:
          //  {
          //    // Create a composite object from which we get the mesh.
          //    CompositeShape compBvh = new CompositeShape();
          //    compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3(0, 0.5f, 0), Matrix.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(
          //        new BoxShape(0.8f, 0.5f, 0.5f),
          //        new Pose(new Vector3(0.5f, 0.7f, 0), Matrix.CreateRotationZ(-(float)MathHelper.ToRadians(15)))));
          //    compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3(0, 1.15f, 0), Matrix.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3(0.6f, 1.15f, 0), Matrix.CreateRotationX(0.3f))));

          //    TriangleMeshShape meshBvhShape = new TriangleMeshShape { Mesh = compBvh.GetMesh(0.01f, 3) };
          //    meshBvhShape.Partition = new AabbTree<int>();
          //    shape = meshBvhShape;
          //    break;
          //  }
          //case 27:
          //  {
          //    // Create a composite object from which we get the mesh.
          //    CompositeShape compBvh = new CompositeShape();
          //    compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3(0, 0.5f, 0), Quaternion.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(
          //        new BoxShape(0.8f, 0.5f, 0.5f),
          //        new Pose(new Vector3(0.5f, 0.7f, 0), Quaternion.CreateRotationZ(-(float)MathHelper.ToRadians(15)))));
          //    compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3(0, 1.15f, 0), Quaternion.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3(0.6f, 1.15f, 0), Quaternion.CreateRotationX(0.3f))));

          //    TriangleMeshShape meshBvhShape = new TriangleMeshShape { Mesh = compBvh.GetMesh(0.01f, 3) };
          //    meshBvhShape.Partition = new AabbTree<int>();
          //    shape = meshBvhShape;
          //    break;
          //  }
          case 28:
            shape = new ConvexPolyhedron(new[]
            {
              new Vector3(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize),
              new Vector3(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize),
              new Vector3(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize)
            });
            break;
          case 29:
            return;
          default:
            currentShape++;
            continue;
        }

        // Create an object with the random shape, pose, color and velocity.
        Pose randomPose = new Pose(
          random.NextVector3(-BoxSize + ObjectSize * 2, BoxSize - ObjectSize * 2),
          random.NextQuaternion());
        var newObject = new MovingGeometricObject
        {
          Pose = randomPose,
          Shape = shape,
          LinearVelocity = random.NextQuaternion().Rotate(new Vector3(MaxLinearVelocity, 0, 0)),
          AngularVelocity = random.NextQuaternion().Rotate(Vector3.Forward)
                            * RandomHelper.Random.NextFloat(0, MaxAngularVelocity),
        };

        if (RandomHelper.Random.NextBool())
          newObject.LinearVelocity = Vector3.Zero;
        if (RandomHelper.Random.NextBool())
          newObject.AngularVelocity = Vector3.Zero;

        if (shape is LineShape || shape is HeightField)
        {
          // Do not move lines or the height field.
          newObject.LinearVelocity = Vector3.Zero;
          newObject.AngularVelocity = Vector3.Zero;
        }

        // Create only 1 heightField!
        if (shape is HeightField)
        {
          if (isFirstHeightField)
          {
            isFirstHeightField = true;
            newObject.Pose = new Pose(new Vector3(-BoxSize, -BoxSize, -BoxSize));
          }
          else
          {
            currentShape++;
            numberOfObjects = 0;
            continue;
          }
        }

        // Add collision object to collision domain.
        _domain.CollisionObjects.Add(new CollisionObject(newObject));

        //co.Type = CollisionObjectType.Trigger;
        //co.Name = "Object" + shape.GetType().Name + "_" + i;
      }
    }
コード例 #27
0
        public override void ComputeCollision(ContactSet contactSet, CollisionQueryType type)
        {
            // Object B should be the transformed shape.
            CollisionObject objectA = contactSet.ObjectA;
            CollisionObject objectB = contactSet.ObjectB;

            // Swap objects if necessary.
            bool swapped = !(objectB.GeometricObject.Shape is TransformedShape);

            if (swapped)
            {
                MathHelper.Swap(ref objectA, ref objectB);
            }

            IGeometricObject geometricObjectB = objectB.GeometricObject;
            TransformedShape transformedShape = geometricObjectB.Shape as TransformedShape;

            // Check if collision objects shapes are correct.
            if (transformedShape == null)
            {
                throw new ArgumentException("The contact set must contain a transformed shape.", "contactSet");
            }

            // Assume no contact.
            contactSet.HaveContact = false;

            // Currently object B has the following structure:
            //
            //  CollisionObject           objectB
            //    GeometricObject           geometricObjectB
            //      Pose                      poseB
            //      Scale                     scaleB
            //      TransformedShape          transformedShape
            //        GeometricObject             childGeometricObject
            //          Pose                      childPose
            //          Scale                     childScale
            //          Shape                     childShape
            //
            // To compute the collisions we temporarily remove the TransformedShape:
            // We replace the original geometric object with a test geometric object and combine the
            // transformations:
            //
            //  CollisionObject           testObjectB
            //    GeometricObject           testGeometricObjectB
            //      Pose                      poseB * childPose
            //      Shape                     childShape
            //      Scale                     scaleB * childScale

            Pose     poseB  = geometricObjectB.Pose;
            Vector3F scaleB = geometricObjectB.Scale;

            // Apply scale to pose and test geometric object.
            // (Note: The scaling is either uniform or the transformed object has no local rotation.
            // Therefore, we only need to apply the scale of the parent to the scale and translation of
            // the child. We can ignore the rotation.)
            IGeometricObject childGeometricObject = transformedShape.Child;
            Pose             childPose            = childGeometricObject.Pose;

            // Non-uniform scaling is not supported for rotated child objects.
            if ((scaleB.X != scaleB.Y || scaleB.Y != scaleB.Z) && childPose.HasRotation)
            {
                throw new NotSupportedException("Computing collisions for transformed shapes with local rotations and non-uniform scaling is not supported.");
            }

            childPose.Position *= scaleB;                 // Apply scaling to local translation.

            var testGeometricObjectB = TestGeometricObject.Create();

            testGeometricObjectB.Shape = childGeometricObject.Shape;
            testGeometricObjectB.Scale = scaleB * childGeometricObject.Scale; // Apply scaling to local scale.
            testGeometricObjectB.Pose  = poseB * childPose;

            var testCollisionObjectB = ResourcePools.TestCollisionObjects.Obtain();

            testCollisionObjectB.SetInternal(objectB, testGeometricObjectB);

            var testContactSet = swapped ? ContactSet.Create(testCollisionObjectB, objectA)
                                   : ContactSet.Create(objectA, testCollisionObjectB);

            testContactSet.IsPerturbationTestAllowed = contactSet.IsPerturbationTestAllowed;

            // Transform contacts into space of child and copy them into the testContactSet.
            //int numberOfOldContacts = contactSet.Count;
            //for (int i = 0; i < numberOfOldContacts; i++)
            //{
            //  Contact contact = contactSet[i];
            //  if (swapped)
            //    contact.PositionALocal = childPose.ToLocalPosition(contact.PositionALocal);
            //  else
            //    contact.PositionBLocal = childPose.ToLocalPosition(contact.PositionBLocal);
            //
            //  testContactSet.Add(contact);
            //}

            // Compute collision.
            var collisionAlgorithm = CollisionDetection.AlgorithmMatrix[objectA, testCollisionObjectB];

            collisionAlgorithm.ComputeCollision(testContactSet, type);

            if (testContactSet.HaveContact)
            {
                contactSet.HaveContact = true;
            }

            // Transform contacts into space of parent TransformShape.
            int numberOfNewContacts = testContactSet.Count;

            for (int i = 0; i < numberOfNewContacts; i++)
            {
                Contact contact = testContactSet[i];
                if (swapped)
                {
                    contact.PositionALocal = childPose.ToWorldPosition(contact.PositionALocal);
                }
                else
                {
                    contact.PositionBLocal = childPose.ToWorldPosition(contact.PositionBLocal);
                }
            }

            // Merge new contacts to contactSet.
            // (If testContactSet contains all original contacts (see commented out part above), we can
            // simply clear contactSet and copy all contacts of testContactSet.)
            //contactSet.Clear();
            //foreach (Contact contact in testContactSet)
            //  contactSet.Add(contact);
            ContactHelper.Merge(contactSet, testContactSet, type, CollisionDetection.ContactPositionTolerance);

            // Recycle temporary objects.
            testContactSet.Recycle();
            ResourcePools.TestCollisionObjects.Recycle(testCollisionObjectB);
            testGeometricObjectB.Recycle();
        }
コード例 #28
0
        public void GeometryException()
        {
            TransformedShape t = new TransformedShape();

            t.Child = null;
        }
コード例 #29
0
 public void GeometryException()
 {
     TransformedShape t = new TransformedShape();
       t.Child = null;
 }
コード例 #30
0
        public void SerializationBinary()
        {
            Pose pose = new Pose(new Vector3F(1, 2, 3));
              PointShape pointShape = new PointShape(3, 4, 5);
              var a = new TransformedShape(new GeometricObject(pointShape, pose));

              // Serialize object.
              var stream = new MemoryStream();
              var formatter = new BinaryFormatter();
              formatter.Serialize(stream, a);

              // Deserialize object.
              stream.Position = 0;
              var deserializer = new BinaryFormatter();
              var b = (TransformedShape)deserializer.Deserialize(stream);

              Assert.AreEqual(a.Child.Pose, b.Child.Pose);
              Assert.AreEqual(((PointShape)a.Child.Shape).Position, ((PointShape)b.Child.Shape).Position);
        }
コード例 #31
0
        public void PropertyChangedTest()
        {
            TransformedShape t = new TransformedShape();
              t.Changed += delegate { _propertyChanged = true; };

              Assert.IsFalse(_propertyChanged);

              ((GeometricObject)t.Child).Shape = new SphereShape(1);
              Assert.IsTrue(_propertyChanged);
              _propertyChanged = false;

              ((SphereShape) t.Child.Shape).Radius = 3;
              Assert.IsTrue(_propertyChanged);
              _propertyChanged = false;

              ((GeometricObject)t.Child).Pose = new Pose(new Vector3F(1, 2, 3));
              Assert.IsTrue(_propertyChanged);
              _propertyChanged = false;

              // Setting Pose to the same value does not create a changed event.
              ((GeometricObject)t.Child).Pose = new Pose(new Vector3F(1, 2, 3));
              Assert.IsFalse(_propertyChanged);
              _propertyChanged = false;

              ((GeometricObject)t.Child).Pose = Pose.Identity;
              Assert.IsTrue(_propertyChanged);
              _propertyChanged = false;

              t.Child = new GeometricObject();
              Assert.IsTrue(_propertyChanged);
              _propertyChanged = false;

              // Setting Pose to the same value does not create a changed event.
              ((GeometricObject)t.Child).Pose = Pose.Identity;
              Assert.IsFalse(_propertyChanged);
              _propertyChanged = false;
        }
コード例 #32
0
        public FigurePickerObject(IGraphicsService graphicsService, Scene scene, CameraObject cameraObject, DebugRenderer debugRenderer)
        {
            _cameraObject  = cameraObject;
            _scene         = scene;
            _debugRenderer = debugRenderer;

            // Create a collision domain which manages all collision objects used for
            // picking: the picking object and the collision objects for figure nodes.
            _collisionDomain = new CollisionDomain(new CollisionDetection());

            // Create the picking object:
            // The picking object represents the mouse cursor or the reticle. Usually
            // a ray is used, but in this example we want to use a cylinder/cone. This
            // allows to check which objects within a certain radius of the reticle. A
            // picking cylinder/cone is helpful for touch devices where the picking is
            // done with an imprecise input method like the human finger.

            // We want to pick objects in 10 pixel radius around the reticle. To determine
            // the world space size of the required cylinder/cone, we can use the projection
            // and the viewport.
            const float pickingRadius = 10;
            var         projection    = _cameraObject.CameraNode.Camera.Projection;
            var         viewport      = graphicsService.GraphicsDevice.Viewport;

            Shape pickingShape;

            if (projection is OrthographicProjection)
            {
                // Use cylinder for orthographic projections:
                // The cylinder is centered at the camera position and reaches from the
                // camera position to the camera far plane. A TransformedShape is used
                // to rotate and translate the cylinder.
                float radius = projection.Width / viewport.Width * pickingRadius;
                pickingShape = new TransformedShape(
                    new GeometricObject(
                        new CylinderShape(radius, projection.Far),
                        new Pose(new Vector3F(0, 0, -projection.Far / 2), Matrix33F.CreateRotationX(ConstantsF.PiOver2))));
            }
            else
            {
                // Use cone for perspective projections:
                // The cone tip is at the camera position and the cone base is at the
                // camera far plane.

                // Compute the radius at the far plane that projects to 10 pixels in screen space.
                float radius = viewport.Unproject(
                    new Vector3(viewport.Width / 2.0f + pickingRadius, viewport.Height / 2.0f, 1),
                    (Matrix)_cameraObject.CameraNode.Camera.Projection.ToMatrix44F(),
                    Matrix.Identity,
                    Matrix.Identity).X;

                // A transformed shape is used to rotate and translate the cone.
                pickingShape = new TransformedShape(
                    new GeometricObject(
                        new ConeShape(radius, projection.Far),
                        new Pose(new Vector3F(0, 0, -projection.Far), Matrix33F.CreateRotationX(ConstantsF.PiOver2))));
            }

            // Create collision object with the picking shape.
            _pickingObject = new CollisionObject(new GeometricObject(pickingShape, _cameraObject.CameraNode.PoseWorld));
        }
コード例 #33
0
        public WaterSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            _graphicsScreen             = new DeferredGraphicsScreen(Services);
            _graphicsScreen.DrawReticle = true;
            GraphicsService.Screens.Insert(0, _graphicsScreen);
            GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

            Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer);
            Services.Register(typeof(IScene), null, _graphicsScreen.Scene);

            // Add gravity and damping to the physics Simulation.
            Simulation.ForceEffects.Add(new Gravity());
            Simulation.ForceEffects.Add(new Damping());

            // Add a custom game object which controls the camera.
            var cameraGameObject = new CameraObject(Services);

            GameObjectService.Objects.Add(cameraGameObject);
            _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode;

            // More standard objects.
            GameObjectService.Objects.Add(new GrabObject(Services));
            GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
            //GameObjectService.Objects.Add(new StaticSkyObject(Services));
            var dynamicSkyObject = new DynamicSkyObject(Services, true, false, true);

            GameObjectService.Objects.Add(dynamicSkyObject);

            // Add a ground plane with some detail to see the water refractions.
            Simulation.RigidBodies.Add(new RigidBody(new PlaneShape(new Vector3(0, 1, 0), 0)));
            GameObjectService.Objects.Add(new StaticObject(Services, "Gravel/Gravel", 1, new Pose(new Vector3(0, 0.001f, 0))));

            GameObjectService.Objects.Add(new DudeObject(Services));
            GameObjectService.Objects.Add(new DynamicObject(Services, 1));
            GameObjectService.Objects.Add(new DynamicObject(Services, 2));
            GameObjectService.Objects.Add(new DynamicObject(Services, 5));
            GameObjectService.Objects.Add(new DynamicObject(Services, 6));
            GameObjectService.Objects.Add(new DynamicObject(Services, 7));
            GameObjectService.Objects.Add(new FogObject(Services)
            {
                AttachToCamera = true
            });

            // The LavaBalls class controls all lava ball instances.
            var lavaBalls = new LavaBallsObject(Services);

            GameObjectService.Objects.Add(lavaBalls);

            // Add a few palm trees.
            var random = new Random(12345);

            for (int i = 0; i < 10; i++)
            {
                Vector3 position    = new Vector3(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5));
                Matrix  orientation = Matrix.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
                float   scale       = random.NextFloat(0.5f, 1.2f);
                GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation)));
            }

            // Define the appearance of the water.
            var water = new Water
            {
                SpecularColor = new Vector3(10f),

                // Small water ripples/waves are created using scrolling normal maps.
                NormalMap0         = ContentManager.Load <Texture2D>("Water/Wave0"),
                NormalMap1         = ContentManager.Load <Texture2D>("Water/Wave1"),
                NormalMap0Scale    = 1.8f,
                NormalMap1Scale    = 2.2f,
                NormalMap0Velocity = new Vector3(-0.02f, 0, 0.03f),
                NormalMap1Velocity = new Vector3(0.02f, 0, -0.03f),
                NormalMap0Strength = 0.5f,
                NormalMap1Strength = 0.5f,

                ReflectionDistortion = 0.2f,
                ReflectionColor      = new Vector3(0.7f),
                RefractionDistortion = 0.05f,
            };

            // Create a box-shaped body of water.
            // We use a TransformedShape containing a BoxShape because the top of the
            // water body must be at height 0.
            var shape = new TransformedShape(new GeometricObject(
                                                 new BoxShape(10, 1, 20),
                                                 new Pose(new Vector3(0, -0.5f, 0))));

            _waterNode0 = new WaterNode(water, shape)
            {
                PoseWorld              = new Pose(new Vector3(-1, 0.5f, 0), Matrix.CreateRotationY(0.1f)),
                SkyboxReflection       = _graphicsScreen.Scene.GetDescendants().OfType <SkyboxNode>().First(),
                DepthBufferWriteEnable = true,
            };
            _graphicsScreen.Scene.Children.Add(_waterNode0);

            // Optional: Create a WaterFlow to move the water using a flow texture.
            _waterFlow0 = new WaterFlow
            {
                FlowMapSpeed     = 0.5f,
                FlowMap          = GenerateFlowMap(),
                CycleDuration    = 3f,
                NoiseMapStrength = 0.1f,
                NoiseMapScale    = 0.5f,
            };
            _waterNode0.Flow = _waterFlow0;

            // Optional: Use a planar reflection instead of the skybox reflection.
            // We add a PlanarReflectionNode as a child of the WaterNode.
            var renderToTexture = new RenderToTexture
            {
                Texture = new RenderTarget2D(GraphicsService.GraphicsDevice, 512, 512, false, SurfaceFormat.HdrBlendable, DepthFormat.None),
            };
            var planarReflectionNode = new PlanarReflectionNode(renderToTexture)
            {
                // Same shape as WaterNode.
                Shape = _waterNode0.Shape,

                // Reflection plane is horizontal.
                NormalLocal = new Vector3(0, 1, 0),
            };

            _waterNode0.PlanarReflection = planarReflectionNode;
            _waterNode0.Children         = new SceneNodeCollection(1)
            {
                planarReflectionNode
            };

            // Create a short river with an inclined water surface.
            // Using a WaterFlow with a SurfaceSlopeSpeed, the water automatically flows
            // down the inclined surface.
            _waterNode1 = new WaterNode(water, GetSpiralShape())
            {
                PoseWorld = new Pose(new Vector3(10, 1.5f, 0), Matrix.CreateRotationY(0.1f)),
                EnableUnderwaterEffect = false,
                SkyboxReflection       = _graphicsScreen.Scene.GetDescendants().OfType <SkyboxNode>().First(),
                Flow = new WaterFlow
                {
                    SurfaceSlopeSpeed = 0.5f,
                    CycleDuration     = 2f,
                    NoiseMapStrength  = 0.1f,
                    NoiseMapScale     = 1,
                }
            };
            _graphicsScreen.Scene.Children.Add(_waterNode1);
        }
コード例 #34
0
ファイル: WaterNode.cs プロジェクト: terrynoya/DigitalRune
        private void Update(bool invalidateRenderData)
        {
            if (invalidateRenderData)
            {
                RenderData.SafeDispose();
            }

            // Update shape.
            if (Volume == null)
            {
                // Use a PlaneShape for an infinite ocean.

                var planeShape = Shape as PlaneShape;
                if (planeShape != null)
                {
                    planeShape.Normal             = new Vector3F(0, 1, 0);
                    planeShape.DistanceFromOrigin = ExtraHeight;
                }
                else
                {
                    Shape = new PlaneShape(new Vector3F(0, 1, 0), ExtraHeight);
                }

                return;
            }

            // Check if we have a valid AABB.
            var aabb = Volume.GetAabb();

            if (!Numeric.IsZeroOrPositiveFinite(aabb.Extent.LengthSquared))
            {
                throw new GraphicsException("Invalid water volume. The water volume must be a finite shape or null.");
            }

            // Apply ExtraHeight. We also apply it horizontally because choppy waves
            // move vertices horizontally too.
            aabb.Minimum.X -= ExtraHeight;

            // Minimum y should be at least max y - ExtraHeight.
            aabb.Minimum.Y  = Math.Min(aabb.Minimum.Y, aabb.Maximum.Y - ExtraHeight);
            aabb.Minimum.Z -= ExtraHeight;
            aabb.Maximum.X += ExtraHeight;
            aabb.Maximum.Y += ExtraHeight;
            aabb.Maximum.Z += ExtraHeight;

            // Create shape from volume AABB.
            if (aabb.Center.IsNumericallyZero)
            {
                // Use BoxShape.
                var boxShape = Shape as BoxShape;
                if (boxShape != null)
                {
                    boxShape.Extent = aabb.Extent;
                }
                else
                {
                    Shape = new BoxShape(aabb.Extent);
                }
            }
            else
            {
                BoxShape boxShape         = null;
                var      transformedShape = Shape as TransformedShape;
                if (transformedShape != null)
                {
                    boxShape = transformedShape.Child.Shape as BoxShape;
                }

                if (boxShape != null)
                {
                    boxShape.Extent = aabb.Extent;
                    ((GeometricObject)transformedShape.Child).Pose = new Pose(aabb.Center);
                }
                else
                {
                    Shape = new TransformedShape(
                        new GeometricObject(new BoxShape(aabb.Extent), new Pose(aabb.Center)));
                }
            }
        }
コード例 #35
0
        public void InnerPoint2()
        {
            TransformedShape t = new TransformedShape
              {
            Child = new GeometricObject
            {
              Pose = new Pose(new Vector3F(0, 1, 0)),
              Shape = new PointShape(1, 0, 0),
            },
              };

              Assert.AreEqual(new Vector3F(1, 1, 0), t.InnerPoint);
        }
コード例 #36
0
        /// <summary>
        /// Converts mesh content to a <see cref="Shape"/>.
        /// </summary>
        /// <param name="input">The root node content.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>The <see cref="Shape"/>.</returns>
        public override Shape Process(NodeContent input, ContentProcessorContext context)
        {
            // ----- Apply Scale factor.
            if (Scale != 1f)
            {
                // The user has set a scale. Use MeshHelper to apply the scale to the whole model.
                Matrix transform = Matrix.CreateScale(Scale);
                MeshHelper.TransformScene(input, transform);
            }

            // ----- Convert Mesh to Shapes
            // The input node is usually a tree of nodes. We need to collect all MeshContent nodes
            // in the tree. The DigitalRune Helper library provides a TreeHelper that can be used
            // to traverse trees using LINQ.
            // The following returns an IEnumerable that contains all nodes of the tree.
            IEnumerable <NodeContent> nodes = TreeHelper.GetSubtree(input, n => n.Children);

            // We only need nodes of type MeshContent.
            IEnumerable <MeshContent> meshes = nodes.OfType <MeshContent>();

            // For each MeshContent we extract one shape and its pose (position and orientation).
            List <Pose>  poses  = new List <Pose>();
            List <Shape> shapes = new List <Shape>();

            foreach (var mesh in meshes)
            {
                if (mesh.Positions.Count == 0)
                {
                    continue;
                }

                Pose  pose  = Pose.Identity;
                Shape shape = null;

                // The meshes in the imported file must follow a naming convention. The end of the name
                // of each mesh must be "Box", "Sphere" or "Convex" to tell us which kind of collision
                // shape we must create.
                if (mesh.Name.EndsWith("Box"))
                {
                    LoadBox(mesh, out pose, out shape);
                }
                else if (mesh.Name.EndsWith("Sphere"))
                {
                    LoadSphere(mesh, out pose, out shape);
                }
                else if (mesh.Name.EndsWith("Convex"))
                {
                    LoadConvex(mesh, out pose, out shape);
                }

                if (shape != null)
                {
                    poses.Add(pose);
                    shapes.Add(shape);
                }
            }

            // The CollisionShapeProcessor exports a single shape.
            Shape collisionShape;

            if (shapes.Count == 0)
            {
                // We did not find any collision shapes. --> Return a dummy shape.
                collisionShape = Shape.Empty;
            }
            else if (shapes.Count == 1)
            {
                // We have found 1 shape.
                if (poses[0].HasRotation || poses[0].HasTranslation)
                {
                    // The shape is not centered in origin of the model space or it is rotated,
                    // therefore we create a TransformedShape that applies the transformation.
                    collisionShape = new TransformedShape(new GeometricObject(shapes[0], poses[0]));
                }
                else
                {
                    // Use the shape directly, there is no translation or rotation we have to apply.
                    collisionShape = shapes[0];
                }
            }
            else
            {
                // We have found several collision shapes. --> Combine all shapes into one CompositeShape.
                CompositeShape compositeShape = new CompositeShape();
                for (int i = 0; i < shapes.Count; i++)
                {
                    compositeShape.Children.Add(new GeometricObject(shapes[i], poses[i]));
                }

                // If the composite shape has many children, the performance is improved if the composite
                // shape uses a spatial partition.
                //compositeShape.Partition = new CompressedAabbTree();

                collisionShape = compositeShape;
            }

            return(collisionShape);
        }
コード例 #37
0
        /// <inheritdoc/>
        /// <exception cref="ArgumentException">
        /// Neither <paramref name="objectA"/> nor <paramref name="objectB"/> is a
        /// <see cref="TransformedShape"/>.
        /// <exception cref="ArgumentNullException">
        /// <paramref name="objectA"/> or <paramref name="objectB"/> is <see langword="null"/>.
        /// </exception>
        /// </exception>
        public override float GetTimeOfImpact(CollisionObject objectA, Pose targetPoseA, CollisionObject objectB, Pose targetPoseB, float allowedPenetration)
        {
            // Most of this code is copied from ComputeCollision() above.

            // We get the child and compute the TOI for the child movement. The child movement is
            // linearly interpolated from start to end pose. - This is not correct if the real center
            // of rotation and the center of the child shape are not equal! But for small rotational
            // movement and small offsets this is acceptable.

            if (objectA == null)
            {
                throw new ArgumentNullException("objectA");
            }
            if (objectB == null)
            {
                throw new ArgumentNullException("objectB");
            }

            // B should be the transformed shape, swap objects if necessary.
            bool swapped = !(objectB.GeometricObject.Shape is TransformedShape);

            if (swapped)
            {
                MathHelper.Swap(ref objectA, ref objectB);
                MathHelper.Swap(ref targetPoseA, ref targetPoseB);
            }

            IGeometricObject geometricObjectB = objectB.GeometricObject;
            TransformedShape transformedShape = geometricObjectB.Shape as TransformedShape;

            // Check if collision objects shapes are correct.
            if (transformedShape == null)
            {
                throw new ArgumentException("objectA or objectB must be a TransformedShape.");
            }

            Pose     poseB  = geometricObjectB.Pose;
            Vector3F scaleB = geometricObjectB.Scale;

            // Note: Non-uniform scaling for rotated child objects is not supported
            // but we might still get a usable TOI query result.

            // Apply scale to pose and test geometric object.
            // (Note: The scaling is either uniform or the transformed object has no local rotation.
            // Therefore, we only need to apply the scale of the parent to the scale and translation of
            // the child. We can ignore the rotation.)
            IGeometricObject childGeometricObject = transformedShape.Child;
            Pose             childPose            = childGeometricObject.Pose;

            childPose.Position *= scaleB;                 // Apply scaling to local translation.

            var testGeometricObjectB = TestGeometricObject.Create();

            testGeometricObjectB.Shape = childGeometricObject.Shape;
            testGeometricObjectB.Scale = scaleB * childGeometricObject.Scale; // Apply scaling to local scale.
            testGeometricObjectB.Pose  = poseB * childPose;

            var testCollisionObjectB = ResourcePools.TestCollisionObjects.Obtain();

            testCollisionObjectB.SetInternal(objectB, testGeometricObjectB);

            // Compute TOI.
            var   collisionAlgorithm = CollisionDetection.AlgorithmMatrix[objectA, testCollisionObjectB];
            float timeOfImpact       = collisionAlgorithm.GetTimeOfImpact(
                objectA, targetPoseA,
                testCollisionObjectB, targetPoseB * childPose,
                allowedPenetration);

            // Recycle temporary objects.
            ResourcePools.TestCollisionObjects.Recycle(testCollisionObjectB);
            testGeometricObjectB.Recycle();

            return(timeOfImpact);
        }