Exemple #1
0
        /// <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();
        }
        /// <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);
        }
        /// <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);
        }
Exemple #4
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);
        }
Exemple #5
0
        ///<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);
        }
Exemple #6
0
        ///<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);
        }
Exemple #7
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);
        }
Exemple #8
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);
        }
        /// <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);
        }
Exemple #10
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();
        }
Exemple #11
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;
        }
Exemple #12
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;
        }
Exemple #13
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);
        }
Exemple #14
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];
        }
        /// <summary>
        /// Recenters the triangle data and computes the volume distribution.
        /// </summary>
        /// <param name="data">Mesh data to analyze.</param>
        /// <returns>Computed center, volume, and volume distribution.</returns>
        private ShapeDistributionInformation ComputeVolumeDistribution(TransformableMeshData data)
        {
            //Compute the surface vertices of the shape.
            ShapeDistributionInformation shapeInformation;

            if (solidity == MobileMeshSolidity.Solid)
            {
                //The following inertia tensor calculation assumes a closed mesh.
                var transformedVertices = CommonResources.GetVectorList();
                if (transformedVertices.Capacity < data.vertices.Length)
                {
                    transformedVertices.Capacity = data.vertices.Length;
                }
                transformedVertices.Count = data.vertices.Length;
                for (int i = 0; i < data.vertices.Length; ++i)
                {
                    data.GetVertexPosition(i, out transformedVertices.Elements[i]);
                }
                InertiaHelper.ComputeShapeDistribution(transformedVertices, data.indices, out shapeInformation.Center, out shapeInformation.Volume, out shapeInformation.VolumeDistribution);
                CommonResources.GiveBack(transformedVertices);
                if (shapeInformation.Volume > F64.C0)
                {
                    return(shapeInformation);
                }
                throw new ArgumentException("A solid mesh must have volume.");
            }
            shapeInformation.Center             = new Vector3();
            shapeInformation.VolumeDistribution = new Matrix3x3();
            Fix64 totalWeight = F64.C0;

            for (int i = 0; i < data.indices.Length; i += 3)
            {
                //Compute the center contribution.
                Vector3 vA, vB, vC;
                data.GetTriangle(i, out vA, out vB, out vC);
                Vector3 vAvB;
                Vector3 vAvC;
                Vector3.Subtract(ref vB, ref vA, out vAvB);
                Vector3.Subtract(ref vC, ref vA, out vAvC);
                Vector3 cross;
                Vector3.Cross(ref vAvB, ref vAvC, out cross);
                Fix64 weight = cross.Length();
                totalWeight += weight;

                Fix64 perVertexWeight = weight * F64.OneThird;
                shapeInformation.Center += perVertexWeight * (vA + vB + vC);

                //Compute the inertia contribution of this triangle.
                //Approximate it using pointmasses positioned at the triangle vertices.
                //(There exists a direct solution, but this approximation will do plenty fine.)
                Matrix3x3 aContribution, bContribution, cContribution;
                InertiaHelper.GetPointContribution(perVertexWeight, ref Toolbox.ZeroVector, ref vA, out aContribution);
                InertiaHelper.GetPointContribution(perVertexWeight, ref Toolbox.ZeroVector, ref vB, out bContribution);
                InertiaHelper.GetPointContribution(perVertexWeight, ref Toolbox.ZeroVector, ref vC, out cContribution);
                Matrix3x3.Add(ref aContribution, ref shapeInformation.VolumeDistribution, out shapeInformation.VolumeDistribution);
                Matrix3x3.Add(ref bContribution, ref shapeInformation.VolumeDistribution, out shapeInformation.VolumeDistribution);
                Matrix3x3.Add(ref cContribution, ref shapeInformation.VolumeDistribution, out shapeInformation.VolumeDistribution);
            }
            shapeInformation.Center /= totalWeight;

            //The extra factor of 2 is used because the cross product length was twice the actual area.
            Matrix3x3.Multiply(ref shapeInformation.VolumeDistribution, F64.C1 / (F64.C2 * totalWeight), out shapeInformation.VolumeDistribution);

            //Move the inertia tensor into position according to the center.
            Matrix3x3 additionalInertia;

            InertiaHelper.GetPointContribution(F64.C0p5, ref Toolbox.ZeroVector, ref shapeInformation.Center, out additionalInertia);
            Matrix3x3.Subtract(ref shapeInformation.VolumeDistribution, ref additionalInertia, out shapeInformation.VolumeDistribution);

            shapeInformation.Volume = F64.C0;


            return(shapeInformation);
        }