コード例 #1
0
        private static void RemoveInsidePoints(RawList <Vector3> points, RawList <int> triangleIndices, RawList <int> outsidePoints)
        {
            var insidePoints = CommonResources.GetIntList();

            //We're going to remove points from this list as we go to prune it down to the truly inner points.
            insidePoints.AddRange(outsidePoints);
            outsidePoints.Clear();

            for (int i = 0; i < triangleIndices.Count && insidePoints.Count > 0; i += 3)
            {
                //Compute the triangle's plane in point-normal representation to test other points against.
                Vector3 normal;
                FindNormal(triangleIndices, points, i, out normal);
                Vector3 p = points.Elements[triangleIndices.Elements[i]];

                for (int j = insidePoints.Count - 1; j >= 0; --j)
                {
                    //Offset from the triangle to the current point, tested against the normal, determines if the current point is visible
                    //from the triangle face.
                    Vector3 offset;
                    Vector3.Subtract(ref points.Elements[insidePoints.Elements[j]], ref p, out offset);
                    float dot;
                    Vector3.Dot(ref offset, ref normal, out dot);
                    //If it's visible, then it's outside!
                    if (dot > 0)
                    {
                        //This point is known to be on the outside; put it on the outside!
                        outsidePoints.Add(insidePoints.Elements[j]);
                        insidePoints.FastRemoveAt(j);
                    }
                }
            }
            CommonResources.GiveBack(insidePoints);
        }
コード例 #2
0
        /// <summary>
        /// Tests to see if a ray's origin is contained within the mesh.
        /// If it is, the hit location is found.
        /// If it isn't, the hit location is still valid if a hit occurred.
        /// If the origin isn't inside and there was no hit, the hit has a T value of Fix64.MaxValue.
        /// </summary>
        /// <param name="ray">Ray in the local space of the shape to test.</param>
        /// <param name="hit">The first hit against the mesh, if any.</param>
        /// <returns>Whether or not the ray origin was in the mesh.</returns>
        public bool IsLocalRayOriginInMesh(ref Ray ray, out RayHit hit)
        {
            var overlapList = CommonResources.GetIntList();

            hit   = new RayHit();
            hit.T = Fix64.MaxValue;
            if (triangleMesh.Tree.GetOverlaps(ray, overlapList))
            {
                bool minimumClockwise = false;
                for (int i = 0; i < overlapList.Count; i++)
                {
                    Vector3 vA, vB, vC;
                    triangleMesh.Data.GetTriangle(overlapList[i], out vA, out vB, out vC);
                    bool   hitClockwise;
                    RayHit tempHit;
                    if (Toolbox.FindRayTriangleIntersection(ref ray, Fix64.MaxValue, ref vA, ref vB, ref vC, out hitClockwise, out tempHit) &&
                        tempHit.T < hit.T)
                    {
                        hit = tempHit;
                        minimumClockwise = hitClockwise;
                    }
                }
                CommonResources.GiveBack(overlapList);

                //If the mesh is hit from behind by the ray on the first hit, then the ray is inside.
                return(hit.T < Fix64.MaxValue && ((SidednessWhenSolid == TriangleSidedness.Clockwise && !minimumClockwise) || (SidednessWhenSolid == TriangleSidedness.Counterclockwise && minimumClockwise)));
            }
            CommonResources.GiveBack(overlapList);
            return(false);
        }
コード例 #3
0
        /// <summary>
        /// Rescales a convex hull shape.
        /// </summary>
        /// <param name="shape">The shape.</param>
        /// <param name="scaleFactor">The scaling factor.</param>
        /// <returns>The new hull.</returns>
        public static ConvexHullShape Rescale(this ConvexHullShape shape, Vector3 scaleFactor)
        {
            ReadOnlyList <Vector3> verts   = shape.Vertices;
            List <Vector3>         newlist = new List <Vector3>(verts.Count);

            foreach (Vector3 vert in verts)
            {
                newlist.Add(vert * scaleFactor);
            }
            double        len       = scaleFactor.Length();
            RawList <int> triangles = CommonResources.GetIntList();

            ConvexHullHelper.GetConvexHull(newlist, triangles);
            InertiaHelper.ComputeShapeDistribution(newlist, triangles, out double volume, out Matrix3x3 volumeDistribution);
            ConvexShapeDescription csd = new ConvexShapeDescription()
            {
                CollisionMargin   = shape.CollisionMargin,
                EntityShapeVolume = new BEPUphysics.CollisionShapes.EntityShapeVolumeDescription()
                {
                    Volume             = volume,
                    VolumeDistribution = volumeDistribution
                },
                MaximumRadius = shape.MaximumRadius * len,
                MinimumRadius = shape.MinimumRadius * len
            };

            CommonResources.GiveBack(triangles);
            return(new ConvexHullShape(newlist, csd));
        }
コード例 #4
0
        /// <summary>
        /// Identifies the points on the surface of hull.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param>
        public static void GetConvexHull(RawList <Vector3> points, IList <Vector3> outputSurfacePoints)
        {
            var indices = CommonResources.GetIntList();

            GetConvexHull(points, indices, outputSurfacePoints);
            CommonResources.GiveBack(indices);
        }
コード例 #5
0
        /// <summary>
        /// Updates the detector volume's interpretation of the mesh.  This should be called when the the TriangleMesh is changed significantly.  This is called automatically if the TriangleMesh property is set.
        /// </summary>
        public void Reinitialize()
        {
            //Pick a point that is known to be outside the mesh as the origin.
            Vector3f origin = (triangleMesh.Tree.BoundingBox.Max - triangleMesh.Tree.BoundingBox.Min) * 1.5f + triangleMesh.Tree.BoundingBox.Min;

            //Pick a direction which will definitely hit the mesh.
            Vector3f a, b, c;

            triangleMesh.Data.GetTriangle(0, out a, out b, out c);
            var direction = (a + b + c) / 3 - origin;

            var ray       = new Ray(origin, direction);
            var triangles = CommonResources.GetIntList();

            triangleMesh.Tree.GetOverlaps(ray, triangles);

            float minimumT = float.MaxValue;

            for (int i = 0; i < triangles.Count; i++)
            {
                triangleMesh.Data.GetTriangle(triangles.Elements[i], out a, out b, out c);

                RayHit hit;
                bool   hitClockwise;
                if (Toolbox.FindRayTriangleIntersection(ref ray, float.MaxValue, ref a, ref b, ref c, out hitClockwise, out hit))
                {
                    if (hit.T < minimumT)
                    {
                        minimumT = hit.T;
                        innerFacingIsClockwise = !hitClockwise;
                    }
                }
            }
            CommonResources.GiveBack(triangles);
        }
コード例 #6
0
        /// <summary>
        /// Computes a convex shape description for a TransformableShape and applies it.
        /// </summary>
        public void UpdateConvexShapeInfo()
        {
            //Compute the volume distribution.
            var samples = CommonResources.GetVectorList();

            if (samples.Capacity < InertiaHelper.SampleDirections.Length)
            {
                samples.Capacity = InertiaHelper.SampleDirections.Length;
            }
            samples.Count = InertiaHelper.SampleDirections.Length;
            for (int i = 0; i < InertiaHelper.SampleDirections.Length; ++i)
            {
                shape.GetLocalExtremePointWithoutMargin(ref InertiaHelper.SampleDirections[i], out samples.Elements[i]);
            }

            var triangles = CommonResources.GetIntList();

            ConvexHullHelper.GetConvexHull(samples, triangles);

            Fix64 volume;

            InertiaHelper.ComputeShapeDistribution(samples, triangles, out volume, out volumeDistribution);
            Volume = volume;

            //Estimate the minimum radius based on the surface mesh.
            MinimumRadius = InertiaHelper.ComputeMinimumRadius(samples, triangles, ref Toolbox.ZeroVector) + collisionMargin;
            MaximumRadius = ComputeMaximumRadius();
            CommonResources.GiveBack(samples);
            CommonResources.GiveBack(triangles);
        }
コード例 #7
0
ファイル: WrappedShape.cs プロジェクト: iamtanmay/BEPUUnity
        /// <summary>
        /// Computes and applies a convex shape description for this WrappedShape.
        /// </summary>
        /// <param name="center">Computed center of the shape before recentering.</param>
        public void UpdateConvexShapeInfo(out Vector3 center)
        {
            //Compute the volume distribution.
            var samples = CommonResources.GetVectorList();

            if (samples.Capacity < InertiaHelper.SampleDirections.Length)
            {
                samples.Capacity = InertiaHelper.SampleDirections.Length;
            }
            samples.Count = InertiaHelper.SampleDirections.Length;
            for (int i = 0; i < InertiaHelper.SampleDirections.Length; ++i)
            {
                GetLocalExtremePoint(InertiaHelper.SampleDirections[i], out samples.Elements[i]);
            }

            var triangles = CommonResources.GetIntList();

            ConvexHullHelper.GetConvexHull(samples, triangles);

            float volume;

            InertiaHelper.ComputeShapeDistribution(samples, triangles, out center, out volume, out volumeDistribution);
            Volume = volume;

            CommonResources.GiveBack(samples);
            CommonResources.GiveBack(triangles);

            //Now recenter the shape and compute the radii estimates.
            for (int i = 0; i < shapes.Count; i++)
            {
                shapes.WrappedList.Elements[i].Transform.Position -= center;
            }
            MinimumRadius = ComputeMinimumRadius();
            MaximumRadius = ComputeMaximumRadius();
        }
コード例 #8
0
        /// <summary>
        /// Identifies the points on the surface of hull.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param>
        public static void GetConvexHull(IList <Vector3> points, IList <Vector3> outputSurfacePoints)
        {
            var rawPoints = CommonResources.GetVectorList();

            rawPoints.AddRange(points);
            GetConvexHull(rawPoints, outputSurfacePoints);
            CommonResources.GiveBack(rawPoints);
        }
コード例 #9
0
        /// <summary>
        /// Determines if a point is contained by the detector volume.
        /// </summary>
        /// <param name="point">Point to check for containment.</param>
        /// <returns>Whether or not the point is contained by the detector volume.</returns>
        public bool IsPointContained(Vector3f point)
        {
            var  triangles = CommonResources.GetIntList();
            bool contained = IsPointContained(ref point, triangles);

            CommonResources.GiveBack(triangles);
            return(contained);
        }
コード例 #10
0
        ///<summary>
        /// Tests a ray against the triangle mesh.
        ///</summary>
        ///<param name="ray">Ray to test against the mesh.</param>
        ///<param name="hitCount">Number of hits between the ray and the mesh.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, out int hitCount)
        {
            var  rayHits  = CommonResources.GetRayHitList();
            bool toReturn = RayCast(ray, rayHits);

            hitCount = rayHits.Count;
            CommonResources.GiveBack(rayHits);
            return(toReturn);
        }
コード例 #11
0
        ///<summary>
        /// Computes the center and surface triangles of a convex hull defined by a point set.
        ///</summary>
        ///<param name="vertices">Point set defining the convex hull.</param>
        ///<param name="outputLocalSurfaceVertices">Local positions of vertices on the convex hull.</param>
        ///<returns>Center of the convex hull.</returns>
        public static Vector3 ComputeCenter(IList <Vector3> vertices, IList <Vector3> outputLocalSurfaceVertices)
        {
            float   volume;
            var     indices  = CommonResources.GetIntList();
            Vector3 toReturn = ComputeCenter(vertices, out volume, indices, outputLocalSurfaceVertices);

            CommonResources.GiveBack(indices);
            return(toReturn);
        }
コード例 #12
0
        /// <summary>
        /// Casts a convex shape against the collidable.
        /// </summary>
        /// <param name="castShape">Shape to cast.</param>
        /// <param name="startingTransform">Initial transform of the shape.</param>
        /// <param name="sweep">Sweep to apply to the shape.</param>
        /// <param name="hit">Hit data, if any.</param>
        /// <returns>Whether or not the cast hit anything.</returns>
        public override bool ConvexCast(CollisionShapes.ConvexShapes.ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweep, out RayHit hit)
        {
            hit = new RayHit();
            BoundingBox boundingBox;

            castShape.GetSweptLocalBoundingBox(ref startingTransform, ref worldTransform, ref sweep, out boundingBox);
            var tri         = PhysicsThreadResources.GetTriangle();
            var hitElements = CommonResources.GetIntList();

            if (this.Shape.TriangleMesh.Tree.GetOverlaps(boundingBox, hitElements))
            {
                hit.T = float.MaxValue;
                for (int i = 0; i < hitElements.Count; i++)
                {
                    Shape.TriangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC);
                    AffineTransform.Transform(ref tri.vA, ref worldTransform, out tri.vA);
                    AffineTransform.Transform(ref tri.vB, ref worldTransform, out tri.vB);
                    AffineTransform.Transform(ref tri.vC, ref worldTransform, out tri.vC);
                    Vector3 center;
                    Vector3.Add(ref tri.vA, ref tri.vB, out center);
                    Vector3.Add(ref center, ref tri.vC, out center);
                    Vector3.Multiply(ref center, 1f / 3f, out center);
                    Vector3.Subtract(ref tri.vA, ref center, out tri.vA);
                    Vector3.Subtract(ref tri.vB, ref center, out tri.vB);
                    Vector3.Subtract(ref tri.vC, ref center, out tri.vC);
                    tri.MaximumRadius = tri.vA.LengthSquared();
                    float radius = tri.vB.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    radius = tri.vC.LengthSquared();
                    if (tri.MaximumRadius < radius)
                    {
                        tri.MaximumRadius = radius;
                    }
                    tri.MaximumRadius   = (float)Math.Sqrt(tri.MaximumRadius);
                    tri.collisionMargin = 0;
                    var triangleTransform = new RigidTransform {
                        Orientation = Quaternion.Identity, Position = center
                    };
                    RayHit tempHit;
                    if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T)
                    {
                        hit = tempHit;
                    }
                }
                tri.MaximumRadius = 0;
                PhysicsThreadResources.GiveBack(tri);
                CommonResources.GiveBack(hitElements);
                return(hit.T != float.MaxValue);
            }
            PhysicsThreadResources.GiveBack(tri);
            CommonResources.GiveBack(hitElements);
            return(false);
        }
コード例 #13
0
ファイル: InertiaHelper.cs プロジェクト: tammukul/Lemma
        ///<summary>
        /// Computes the volume and volume distribution of a shape based on a given center.
        ///</summary>
        ///<param name="shape">Shape to compute the volume information of.</param>
        ///<param name="center">Location to use as the center of the shape when computing the volume distribution.</param>
        ///<param name="volume">Volume of the shape.</param>
        ///<returns>Volume distribution of the shape.</returns>
        public static Matrix3x3 ComputeVolumeDistribution(ConvexShape shape, ref Vector3 center, out float volume)
        {
            var pointContributions = CommonResources.GetVectorList();

            GetPoints(shape, out volume, pointContributions);
            Matrix3x3 volumeDistribution = ComputeVolumeDistribution(pointContributions, ref center);

            CommonResources.GiveBack(pointContributions);
            return(volumeDistribution);
        }
コード例 #14
0
        ///<summary>
        /// Computes the center and volume of a convex hull defined by a pointset.
        ///</summary>
        ///<param name="vertices">Point set defining the convex hull.</param>
        ///<param name="volume">Volume of the convex hull.</param>
        ///<returns>Center of the convex hull.</returns>
        public static Vector3 ComputeCenter(IList <Vector3> vertices, out float volume)
        {
            var     localSurfaceVertices = CommonResources.GetVectorList();
            var     surfaceTriangles     = CommonResources.GetIntList();
            Vector3 toReturn             = ComputeCenter(vertices, out volume, surfaceTriangles, localSurfaceVertices);

            CommonResources.GiveBack(localSurfaceVertices);
            CommonResources.GiveBack(surfaceTriangles);
            return(toReturn);
        }
コード例 #15
0
ファイル: InertiaHelper.cs プロジェクト: tammukul/Lemma
        ///<summary>
        /// Computes the center and volume of a convex shape.
        ///</summary>
        ///<param name="shape">Shape to compute the center of.</param>
        ///<param name="volume">Volume of the shape.</param>
        ///<returns>Center of the shape.</returns>
        public static Vector3 ComputeCenter(ConvexShape shape, out float volume)
        {
            var pointContributions = CommonResources.GetVectorList();

            GetPoints(shape, out volume, pointContributions);
            Vector3 center = AveragePoints(pointContributions);

            CommonResources.GiveBack(pointContributions);
            MathChecker.Validate(center);
            return(center);
        }
コード例 #16
0
        protected override void UpdateContainedPairs(Fix64 dt)
        {
            var overlappedElements = CommonResources.GetIntList();

            mesh.Mesh.Tree.GetOverlaps(mobileMesh.boundingBox, overlappedElements);
            for (int i = 0; i < overlappedElements.Count; i++)
            {
                TryToAdd(overlappedElements.Elements[i]);
            }

            CommonResources.GiveBack(overlappedElements);
        }
コード例 #17
0
        /// <summary>
        /// Computes the volume distribution of the shape as well as its volume.
        /// The volume distribution can be used to compute inertia tensors when
        /// paired with mass and other tuning factors.
        /// </summary>
        /// <param name="volume">Volume of the shape.</param>
        /// <returns>Volume distribution of the shape.</returns>
        public override Matrix3x3 ComputeVolumeDistribution(out float volume)
        {
            var surfaceTriangles = CommonResources.GetIntList();
            var surfaceVertices  = CommonResources.GetVectorList();

            ComputeCenter(out volume, surfaceTriangles, surfaceVertices);
            Matrix3x3 toReturn = ComputeVolumeDistribution(volume, surfaceTriangles);

            CommonResources.GiveBack(surfaceTriangles);
            CommonResources.GiveBack(surfaceVertices);
            return(toReturn);
        }
コード例 #18
0
        /// <summary>
        /// Removes redundant points.  Two points are redundant if they occupy the same hash grid cell.
        /// </summary>
        /// <param name="points">List of points to prune.</param>
        /// <param name="cellSize">Size of cells to determine redundancy.</param>
        public static void RemoveRedundantPoints(IList <Vector3> points, double cellSize)
        {
            var rawPoints = CommonResources.GetVectorList();

            rawPoints.AddRange(points);
            RemoveRedundantPoints(rawPoints, cellSize);
            points.Clear();
            for (int i = 0; i < rawPoints.Count; ++i)
            {
                points.Add(rawPoints.Elements[i]);
            }
            CommonResources.GiveBack(rawPoints);
        }
コード例 #19
0
        /// <summary>
        /// Identifies the points on the surface of hull.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull.
        /// Each group of 3 indices represents a triangle on the surface of the hull.</param>
        /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param>
        public static void GetConvexHull(IList <Vector3> points, IList <int> outputTriangleIndices, IList <Vector3> outputSurfacePoints)
        {
            var rawPoints  = CommonResources.GetVectorList();
            var rawIndices = CommonResources.GetIntList();

            rawPoints.AddRange(points);
            GetConvexHull(rawPoints, rawIndices, outputSurfacePoints);
            CommonResources.GiveBack(rawPoints);
            for (int i = 0; i < rawIndices.Count; i++)
            {
                outputTriangleIndices.Add(rawIndices[i]);
            }
            CommonResources.GiveBack(rawIndices);
        }
コード例 #20
0
        ///<summary>
        /// Constructs a new convex hull shape.
        /// The point set will be recentered on the local origin.
        ///</summary>
        ///<param name="vertices">Point set to use to construct the convex hull.</param>
        /// <param name="center">Computed center of the convex hull shape prior to recentering.</param>
        ///<exception cref="ArgumentException">Thrown when the point set is empty.</exception>
        public ConvexHullShape(IList <Vector3> vertices, out Vector3 center)
        {
            if (vertices.Count == 0)
            {
                throw new ArgumentException("Vertices list used to create a ConvexHullShape cannot be empty.");
            }

            var surfaceVertices = CommonResources.GetVectorList();

            center        = ComputeCenter(vertices, surfaceVertices);
            this.vertices = new RawList <Vector3>(surfaceVertices);
            CommonResources.GiveBack(surfaceVertices);

            OnShapeChanged();
        }
コード例 #21
0
        protected override void UpdateContainedPairs(float dt)
        {
            var         overlappedElements = CommonResources.GetIntList();
            BoundingBox localBoundingBox;

            System.Numerics.Vector3 sweep;
            Vector3Ex.Multiply(ref mobileMesh.entity.linearVelocity, dt, out sweep);
            mobileMesh.Shape.GetSweptLocalBoundingBox(ref mobileMesh.worldTransform, ref mesh.worldTransform, ref sweep, out localBoundingBox);
            mesh.Shape.TriangleMesh.Tree.GetOverlaps(localBoundingBox, overlappedElements);
            for (int i = 0; i < overlappedElements.Count; i++)
            {
                TryToAdd(overlappedElements.Elements[i]);
            }

            CommonResources.GiveBack(overlappedElements);
        }
コード例 #22
0
        /// <summary>
        /// Identifies the points on the surface of hull.
        /// </summary>
        /// <param name="points">List of points in the set.</param>
        /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull.
        /// Each group of 3 indices represents a triangle on the surface of the hull.</param>
        /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param>
        public static void GetConvexHull(RawList <Vector3> points, RawList <int> outputTriangleIndices, IList <Vector3> outputSurfacePoints)
        {
            GetConvexHull(points, outputTriangleIndices);

            var alreadyContainedIndices = CommonResources.GetIntSet();

            for (int i = outputTriangleIndices.Count - 1; i >= 0; i--)
            {
                int index = outputTriangleIndices[i];
                if (alreadyContainedIndices.Add(index))
                {
                    outputSurfacePoints.Add(points[index]);
                }
            }

            CommonResources.GiveBack(alreadyContainedIndices);
        }
コード例 #23
0
        ///<summary>
        /// Tests a ray against the triangle mesh.
        ///</summary>
        ///<param name="ray">Ray to test against the mesh.</param>
        /// <param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        /// <param name="sidedness">Sidedness to apply to the mesh for the ray cast.</param>
        ///<param name="hits">Hit data for the ray, if any.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, IList <RayHit> hits)
        {
            var hitElements = CommonResources.GetIntList();

            tree.GetOverlaps(ray, maximumLength, hitElements);
            for (int i = 0; i < hitElements.Count; i++)
            {
                Vector3 v1, v2, v3;
                data.GetTriangle(hitElements[i], out v1, out v2, out v3);
                RayHit hit;
                if (Toolbox.FindRayTriangleIntersection(ref ray, maximumLength, sidedness, ref v1, ref v2, ref v3, out hit))
                {
                    hits.Add(hit);
                }
            }
            CommonResources.GiveBack(hitElements);
            return(hits.Count > 0);
        }
コード例 #24
0
        /// <summary>
        /// Computes and applies a convex shape description for this MinkowskiSumShape.
        /// </summary>
        /// <returns>Description required to define a convex shape.</returns>
        public void UpdateConvexShapeInfo()
        {
            //Compute the volume distribution.
            RawList <Vector3> samples = CommonResources.GetVectorList();

            if (samples.Capacity < InertiaHelper.SampleDirections.Length)
            {
                samples.Capacity = InertiaHelper.SampleDirections.Length;
            }

            samples.Count = InertiaHelper.SampleDirections.Length;
            for (int i = 0; i < InertiaHelper.SampleDirections.Length; ++i)
            {
                GetLocalExtremePoint(InertiaHelper.SampleDirections[i], out samples.Elements[i]);
            }

            RawList <int> triangles = CommonResources.GetIntList();

            ConvexHullHelper.GetConvexHull(samples, triangles);

            float   volume;
            Vector3 center;

            InertiaHelper.ComputeShapeDistribution(samples, triangles, out center, out volume, out volumeDistribution);
            Volume = volume;

            //Recenter the shape.
            localOffset = -center;
            CommonResources.GiveBack(samples);
            CommonResources.GiveBack(triangles);

            //Compute the radii.
            float minRadius = 0, maxRadius = 0;

            for (int i = 0; i < Shapes.Count; i++)
            {
                minRadius += Shapes.WrappedList.Elements[i].CollisionShape.MinimumRadius;
                maxRadius += Shapes.WrappedList.Elements[i].CollisionShape.MaximumRadius;
            }

            MinimumRadius = minRadius + collisionMargin;
            MaximumRadius = maxRadius + collisionMargin;
        }
コード例 #25
0
        ///<summary>
        /// Constructs a new convex hull shape.
        /// The point set will be recentered on the local origin.
        ///</summary>
        ///<param name="vertices">Point set to use to construct the convex hull.</param>
        /// <param name="center">Computed center of the convex hull shape prior to recentering.</param>
        ///<exception cref="ArgumentException">Thrown when the point set is empty.</exception>
        public ConvexHullShape(IList <Vector3> vertices, out Vector3 center)
        {
            if (vertices.Count == 0)
            {
                throw new ArgumentException("Vertices list used to create a ConvexHullShape cannot be empty.");
            }

            var surfaceVertices     = CommonResources.GetVectorList();
            var hullTriangleIndices = CommonResources.GetIntList();

            UpdateConvexShapeInfo(ComputeDescription(vertices, collisionMargin, out center, hullTriangleIndices, surfaceVertices));
            this.vertices = surfaceVertices.ToArray();

            CommonResources.GiveBack(hullTriangleIndices);
            CommonResources.GiveBack(surfaceVertices);

            unexpandedMaximumRadius = MaximumRadius - collisionMargin;
            unexpandedMinimumRadius = MinimumRadius - collisionMargin;
        }
コード例 #26
0
        ///<summary>
        /// Computes the center, volume, and surface triangles of a convex hull defined by a point set.
        ///</summary>
        ///<param name="vertices">Point set defining the convex hull.</param>
        ///<param name="volume">Volume of the convex hull.</param>
        ///<param name="outputSurfaceTriangles">Indices of surface triangles of the convex hull.</param>
        ///<param name="outputLocalSurfaceVertices">Local positions of vertices on the convex hull.</param>
        ///<returns>Center of the convex hull.</returns>
        public static Vector3 ComputeCenter(IList <Vector3> vertices, out float volume, IList <int> outputSurfaceTriangles, IList <Vector3> outputLocalSurfaceVertices)
        {
            Vector3 centroid = Toolbox.ZeroVector;

            for (int k = 0; k < vertices.Count; k++)
            {
                centroid += vertices[k];
            }
            centroid /= vertices.Count;

            //Toolbox.GetConvexHull(vertices, outputSurfaceTriangles, outputLocalSurfaceVertices);
            ConvexHullHelper.GetConvexHull(vertices, outputSurfaceTriangles, outputLocalSurfaceVertices);

            volume = 0;
            var volumes   = CommonResources.GetFloatList();
            var centroids = CommonResources.GetVectorList();

            for (int k = 0; k < outputSurfaceTriangles.Count; k += 3)
            {
                volumes.Add(Vector3.Dot(
                                Vector3.Cross(vertices[outputSurfaceTriangles[k + 1]] - vertices[outputSurfaceTriangles[k]],
                                              vertices[outputSurfaceTriangles[k + 2]] - vertices[outputSurfaceTriangles[k]]),
                                centroid - vertices[outputSurfaceTriangles[k]]));
                volume += volumes[k / 3];
                centroids.Add((vertices[outputSurfaceTriangles[k]] + vertices[outputSurfaceTriangles[k + 1]] + vertices[outputSurfaceTriangles[k + 2]] + centroid) / 4);
            }
            Vector3 center = Toolbox.ZeroVector;

            for (int k = 0; k < centroids.Count; k++)
            {
                center += centroids[k] * (volumes[k] / volume);
            }
            volume /= 6;
            for (int k = 0; k < outputLocalSurfaceVertices.Count; k++)
            {
                outputLocalSurfaceVertices[k] -= center;
            }
            CommonResources.GiveBack(centroids);
            CommonResources.GiveBack(volumes);
            return(center);
        }
コード例 #27
0
        /// <summary>
        /// Recalculates the bounding box of the fluid based on its depth, surface normal, and surface triangles.
        /// </summary>
        public void RecalculateBoundingBox()
        {
            var points = CommonResources.GetVectorList();

            foreach (var tri in SurfaceTriangles)
            {
                points.Add(tri[0]);
                points.Add(tri[1]);
                points.Add(tri[2]);
                points.Add(tri[0] - upVector * MaxDepth);
                points.Add(tri[1] - upVector * MaxDepth);
                points.Add(tri[2] - upVector * MaxDepth);
            }
            boundingBox = BoundingBox.CreateFromPoints(points);
            CommonResources.GiveBack(points);

            //Compute the transforms used to pull objects into fluid local space.
            Quaternion.GetQuaternionBetweenNormalizedVectors(ref Toolbox.UpVector, ref upVector, out surfaceTransform.Orientation);
            Matrix3f.FromQuaternion(ref surfaceTransform.Orientation, out toSurfaceRotationMatrix);
            surfaceTransform.Position = surfaceTriangles[0][0];
        }
コード例 #28
0
        protected override void UpdateContainedPairs(Fix64 dt)
        {
            var             overlappedElements = CommonResources.GetIntList();
            BoundingBox     localBoundingBox;
            AffineTransform meshTransform;

            AffineTransform.CreateFromRigidTransform(ref mesh.worldTransform, out meshTransform);

            Vector3 sweep;

            Vector3.Subtract(ref mobileMesh.entity.linearVelocity, ref mesh.entity.linearVelocity, out sweep);
            Vector3.Multiply(ref sweep, dt, out sweep);
            mobileMesh.Shape.GetSweptLocalBoundingBox(ref mobileMesh.worldTransform, ref meshTransform, ref sweep, out localBoundingBox);
            mesh.Shape.TriangleMesh.Tree.GetOverlaps(localBoundingBox, overlappedElements);
            for (int i = 0; i < overlappedElements.Count; i++)
            {
                TryToAdd(overlappedElements.Elements[i]);
            }

            CommonResources.GiveBack(overlappedElements);
        }
コード例 #29
0
        ///<summary>
        /// Tests a ray against the triangle mesh.
        ///</summary>
        ///<param name="ray">Ray to test against the mesh.</param>
        /// <param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param>
        /// <param name="sidedness">Sidedness to apply to the mesh for the ray cast.</param>
        ///<param name="rayHit">Hit data for the ray, if any.</param>
        ///<returns>Whether or not the ray hit the mesh.</returns>
        public bool RayCast(Ray ray, float maximumLength, TriangleSidedness sidedness, out RayHit rayHit)
        {
            var  rayHits  = CommonResources.GetRayHitList();
            bool toReturn = RayCast(ray, maximumLength, sidedness, rayHits);

            if (toReturn)
            {
                rayHit = rayHits[0];
                for (int i = 1; i < rayHits.Count; i++)
                {
                    RayHit hit = rayHits[i];
                    if (hit.T < rayHit.T)
                    {
                        rayHit = hit;
                    }
                }
            }
            else
            {
                rayHit = new RayHit();
            }
            CommonResources.GiveBack(rayHits);
            return(toReturn);
        }
コード例 #30
0
        private static void ComputeInitialTetrahedron(RawList <Vector3> points, RawList <int> outsidePointCandidates, RawList <int> triangleIndices, out Vector3 centroid)
        {
            //Find four points on the hull.
            //We'll start with using the x axis to identify two points on the hull.
            int     a, b, c, d;
            Vector3 direction;
            //Find the extreme points along the x axis.
            float minimumX = float.MaxValue, maximumX = -float.MaxValue;
            int   minimumXIndex = 0, maximumXIndex = 0;

            for (int i = 0; i < points.Count; ++i)
            {
                var v = points.Elements[i];
                if (v.X > maximumX)
                {
                    maximumX      = v.X;
                    maximumXIndex = i;
                }
                else if (v.X < minimumX)
                {
                    minimumX      = v.X;
                    minimumXIndex = i;
                }
            }
            a = minimumXIndex;
            b = maximumXIndex;
            //Check for redundancies..
            if (a == b)
            {
                throw new ArgumentException("Point set is degenerate; convex hulls must have volume.");
            }

            //Now, use a second axis perpendicular to the two points we found.
            Vector3 ab;

            Vector3.Subtract(ref points.Elements[b], ref points.Elements[a], out ab);
            Vector3.Cross(ref ab, ref Toolbox.UpVector, out direction);
            if (direction.LengthSquared() < Toolbox.Epsilon)
            {
                Vector3.Cross(ref ab, ref Toolbox.RightVector, out direction);
            }
            float minimumDot, maximumDot;
            int   minimumIndex, maximumIndex;

            GetExtremePoints(ref direction, points, out maximumDot, out minimumDot, out maximumIndex, out minimumIndex);
            //Compare the location of the extreme points to the location of the axis.
            float dot;

            Vector3.Dot(ref direction, ref points.Elements[a], out dot);
            //Use the point further from the axis.
            if (Math.Abs(dot - minimumDot) > Math.Abs(dot - maximumDot))
            {
                //In this case, we should use the minimum index.
                c = minimumIndex;
            }
            else
            {
                //In this case, we should use the maximum index.
                c = maximumIndex;
            }

            //Check for redundancies..
            if (a == c || b == c)
            {
                throw new ArgumentException("Point set is degenerate; convex hulls must have volume.");
            }

            //Use a third axis perpendicular to the plane defined by the three unique points a, b, and c.
            Vector3 ac;

            Vector3.Subtract(ref points.Elements[c], ref points.Elements[a], out ac);
            Vector3.Cross(ref ab, ref ac, out direction);

            GetExtremePoints(ref direction, points, out maximumDot, out minimumDot, out maximumIndex, out minimumIndex);
            //Compare the location of the extreme points to the location of the plane.
            Vector3.Dot(ref direction, ref points.Elements[a], out dot);
            //Use the point further from the plane.
            if (Math.Abs(dot - minimumDot) > Math.Abs(dot - maximumDot))
            {
                //In this case, we should use the minimum index.
                d = minimumIndex;
            }
            else
            {
                //In this case, we should use the maximum index.
                d = maximumIndex;
            }

            //Check for redundancies..
            if (a == d || b == d || c == d)
            {
                throw new ArgumentException("Point set is degenerate; convex hulls must have volume.");
            }

            //Add the triangles.
            triangleIndices.Add(a);
            triangleIndices.Add(b);
            triangleIndices.Add(c);

            triangleIndices.Add(a);
            triangleIndices.Add(b);
            triangleIndices.Add(d);

            triangleIndices.Add(a);
            triangleIndices.Add(c);
            triangleIndices.Add(d);

            triangleIndices.Add(b);
            triangleIndices.Add(c);
            triangleIndices.Add(d);

            //The centroid is guaranteed to be within the convex hull.  It will be used to verify the windings of triangles throughout the hull process.
            Vector3.Add(ref points.Elements[a], ref points.Elements[b], out centroid);
            Vector3.Add(ref centroid, ref points.Elements[c], out centroid);
            Vector3.Add(ref centroid, ref points.Elements[d], out centroid);
            Vector3.Multiply(ref centroid, 0.25f, out centroid);

            for (int i = 0; i < triangleIndices.Count; i += 3)
            {
                var vA = points.Elements[triangleIndices.Elements[i]];
                var vB = points.Elements[triangleIndices.Elements[i + 1]];
                var vC = points.Elements[triangleIndices.Elements[i + 2]];

                //Check the signed volume of a parallelepiped with the edges of this triangle and the centroid.
                Vector3 cross;
                Vector3.Subtract(ref vB, ref vA, out ab);
                Vector3.Subtract(ref vC, ref vA, out ac);
                Vector3.Cross(ref ac, ref ab, out cross);
                Vector3 offset;
                Vector3.Subtract(ref vA, ref centroid, out offset);
                float volume;
                Vector3.Dot(ref offset, ref cross, out volume);
                //This volume/cross product could also be used to check for degeneracy, but we already tested for that.
                if (Math.Abs(volume) < Toolbox.BigEpsilon)
                {
                    throw new ArgumentException("Point set is degenerate; convex hulls must have volume.");
                }
                if (volume < 0)
                {
                    //If the signed volume is negative, that means the triangle's winding is opposite of what we want.
                    //Flip it around!
                    var temp = triangleIndices.Elements[i];
                    triangleIndices.Elements[i]     = triangleIndices.Elements[i + 1];
                    triangleIndices.Elements[i + 1] = temp;
                }
            }

            //Points which belong to the tetrahedra are guaranteed to be 'in' the convex hull. Do not allow them to be considered.
            var tetrahedronIndices = CommonResources.GetIntList();

            tetrahedronIndices.Add(a);
            tetrahedronIndices.Add(b);
            tetrahedronIndices.Add(c);
            tetrahedronIndices.Add(d);
            //Sort the indices to allow a linear time loop.
            Array.Sort(tetrahedronIndices.Elements, 0, 4);
            int tetrahedronIndex = 0;

            for (int i = 0; i < points.Count; ++i)
            {
                if (tetrahedronIndex < 4 && i == tetrahedronIndices[tetrahedronIndex])
                {
                    //Don't add a tetrahedron index. Now that we've found this index, though, move on to the next one.
                    ++tetrahedronIndex;
                }
                else
                {
                    outsidePointCandidates.Add(i);
                }
            }
            CommonResources.GiveBack(tetrahedronIndices);
        }