Exemplo n.º 1
0
        ///<summary>
        /// Constructs a new mobile mesh shape.
        ///</summary>
        ///<param name="vertices">Vertices of the mesh.</param>
        ///<param name="indices">Indices of the mesh.</param>
        ///<param name="localTransform">Local transform to apply to the shape.</param>
        ///<param name="solidity">Solidity state of the shape.</param>
        public MobileMeshShape(Vector3[] vertices, int[] indices, AffineTransform localTransform, MobileMeshSolidity solidity)
        {
            this.solidity = solidity;
            var data = new TransformableMeshData(vertices, indices, localTransform);
            var shapeDistributionInformation = ComputeVolumeDistribution(data);

            data.worldTransform.Translation -= shapeDistributionInformation.Center;

            triangleMesh = new TriangleMesh(data);

            UpdateEntityShapeVolume(new EntityShapeVolumeDescription {
                Volume = shapeDistributionInformation.Volume, VolumeDistribution = shapeDistributionInformation.VolumeDistribution
            });

            ComputeSolidSidedness();

            UpdateSurfaceVertices();
        }
Exemplo n.º 2
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 > 0)
                {
                    return(shapeInformation);
                }
                throw new ArgumentException("A solid mesh must have volume.");
            }
            shapeInformation.Center             = new Vector3();
            shapeInformation.VolumeDistribution = new Matrix3x3();
            float totalWeight = 0;

            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);
                float weight = cross.Length();
                totalWeight += weight;

                float perVertexWeight = weight * (1f / 3f);
                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, 1 / (2 * totalWeight), out shapeInformation.VolumeDistribution);

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

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

            shapeInformation.Volume = 0;


            return(shapeInformation);
        }