public static bool CollisionTest(Ray ray, IPhysical obj, PhysicsMesh mesh, out float dist) { Vector3 start = new Vector3(ray.X, ray.Y, ray.Z); Vector3 direction = new Vector3(ray.I, ray.J, ray.K); dist = Single.MaxValue; // Construct a matrix to transform to scene space Matrix4 transform = Matrix4.Identity; transform *= Matrix4.CreateScale(obj.Scale); transform *= Matrix4.CreateFromQuaternion(obj.RelativeRotation); transform *= Matrix4.CreateTranslation(obj.RelativePosition); ILinkable parent = obj.Parent; if (parent != null) { // Apply parent rotation and translation transform *= Matrix4.CreateFromQuaternion(parent.RelativeRotation); transform *= Matrix4.CreateTranslation(parent.RelativePosition); } // Iterate through all of the triangles in the mesh, doing a ray-triangle intersection for (int i = 0; i < mesh.Indices.Length; i += 3) { Vector3 point0 = mesh.Vertices[mesh.Indices[i + 0]] * transform; Vector3 point1 = mesh.Vertices[mesh.Indices[i + 1]] * transform; Vector3 point2 = mesh.Vertices[mesh.Indices[i + 2]] * transform; float thisDist; if (RayTriangle.CollisionTestCull(start, direction, point0, point1, point2, out thisDist)) { if (thisDist < dist) dist = thisDist; } } return dist < Single.MaxValue; }
/// <summary> /// Calculates the approximate volume of a scaled mesh /// </summary> /// <param name="mesh">Mesh data</param> /// <param name="scale">Object scale</param> /// <returns>Approximate volume of the mesh</returns> public static float GetMeshVolume(PhysicsMesh mesh, Vector3 scale) { const float OO_SIX = 1f / 6f; double volume = 0.0f; // Formula adapted from Stan Melax's algorithm: <http://www.melax.com/volint.html> for (int i = 0; i < mesh.Indices.Length; i += 3) { Vector3 v0 = mesh.Vertices[mesh.Indices[i + 0]]; Vector3 v1 = mesh.Vertices[mesh.Indices[i + 1]]; Vector3 v2 = mesh.Vertices[mesh.Indices[i + 2]]; volume += Determinant3x3(v0, v1, v2); } return (float)(volume * OO_SIX) * scale.X * scale.Y * scale.Z; }