/// <summary> /// Precomputes the transform to bring triangles from their native local space to the local space of the convex. /// </summary> /// <param name="convexInverseWorldTransform">Inverse of the world transform of the convex shape.</param> /// <param name="fromMeshLocalToConvexLocal">Transform to apply to native local triangles to bring them into the local space of the convex.</param> protected override void PrecomputeTriangleTransform(ref AffineTransform convexInverseWorldTransform, out AffineTransform fromMeshLocalToConvexLocal) { //StaticMeshes only have transformable mesh data. var data = ((TransformableMeshData)mesh.Mesh.Data); AffineTransform.Multiply(ref data.worldTransform, ref convexInverseWorldTransform, out fromMeshLocalToConvexLocal); }
//Transform the convex into the space of something else. /// <summary> /// Gets the bounding box of the convex shape transformed first into world space, and then into the local space of another affine transform. /// </summary> /// <param name="shapeTransform">Transform to use to put the shape into world space.</param> /// <param name="spaceTransform">Used as the frame of reference to compute the bounding box. /// In effect, the shape is transformed by the inverse of the space transform to compute its bounding box in local space.</param> /// <param name="boundingBox">Bounding box in the local space.</param> public void GetLocalBoundingBox(ref RigidTransform shapeTransform, ref AffineTransform spaceTransform, out BoundingBox boundingBox) { #if !WINDOWS boundingBox = new BoundingBox(); #endif //TODO: This method peforms quite a few sqrts because the collision margin can get scaled, and so cannot be applied as a final step. //There should be a better way to do this. At the very least, it should be possible to avoid the 6 square roots involved currently. //If this shows a a bottleneck, it might be best to virtualize this function and implement a per-shape variant. //Also... It might be better just to have the internal function be a GetBoundingBox that takes an AffineTransform, and an outer function //does the local space fiddling. //Move forward into convex's space, backwards into the new space's local space. AffineTransform transform; AffineTransform.Invert(ref spaceTransform, out transform); AffineTransform.Multiply(ref shapeTransform, ref transform, out transform); //Sample the local directions from the orientation matrix, implicitly transposed. Vector3 right; var direction = new Vector3(transform.LinearTransform.M11, transform.LinearTransform.M21, transform.LinearTransform.M31); GetLocalExtremePoint(direction, out right); Vector3 left; direction = new Vector3(-transform.LinearTransform.M11, -transform.LinearTransform.M21, -transform.LinearTransform.M31); GetLocalExtremePoint(direction, out left); Vector3 up; direction = new Vector3(transform.LinearTransform.M12, transform.LinearTransform.M22, transform.LinearTransform.M32); GetLocalExtremePoint(direction, out up); Vector3 down; direction = new Vector3(-transform.LinearTransform.M12, -transform.LinearTransform.M22, -transform.LinearTransform.M32); GetLocalExtremePoint(direction, out down); Vector3 backward; direction = new Vector3(transform.LinearTransform.M13, transform.LinearTransform.M23, transform.LinearTransform.M33); GetLocalExtremePoint(direction, out backward); Vector3 forward; direction = new Vector3(-transform.LinearTransform.M13, -transform.LinearTransform.M23, -transform.LinearTransform.M33); GetLocalExtremePoint(direction, out forward); //Rather than transforming each axis independently (and doing three times as many operations as required), just get the 6 required values directly. Vector3 positive, negative; TransformLocalExtremePoints(ref right, ref up, ref backward, ref transform.LinearTransform, out positive); TransformLocalExtremePoints(ref left, ref down, ref forward, ref transform.LinearTransform, out negative); //The positive and negative vectors represent the X, Y and Z coordinates of the extreme points in world space along the world space axes. boundingBox.Max.X = transform.Translation.X + positive.X; boundingBox.Max.Y = transform.Translation.Y + positive.Y; boundingBox.Max.Z = transform.Translation.Z + positive.Z; boundingBox.Min.X = transform.Translation.X + negative.X; boundingBox.Min.Y = transform.Translation.Y + negative.Y; boundingBox.Min.Z = transform.Translation.Z + negative.Z; }
/// <summary> /// Precomputes the transform to bring triangles from their native local space to the local space of the convex. /// </summary> /// <param name="convexInverseWorldTransform">Inverse of the world transform of the convex shape.</param> /// <param name="fromMeshLocalToConvexLocal">Transform to apply to native local triangles to bring them into the local space of the convex.</param> protected override void PrecomputeTriangleTransform(ref AffineTransform convexInverseWorldTransform, out AffineTransform fromMeshLocalToConvexLocal) { //MobileMeshes only have TransformableMeshData sources. var data = ((TransformableMeshData)mesh.Shape.TriangleMesh.Data); //The mobile mesh has a shape-based transform followed by the rigid body transform. AffineTransform mobileMeshWorldTransform; AffineTransform.CreateFromRigidTransform(ref mesh.worldTransform, out mobileMeshWorldTransform); AffineTransform combinedMobileMeshWorldTransform; AffineTransform.Multiply(ref data.worldTransform, ref mobileMeshWorldTransform, out combinedMobileMeshWorldTransform); AffineTransform.Multiply(ref combinedMobileMeshWorldTransform, ref convexInverseWorldTransform, out fromMeshLocalToConvexLocal); }
/// <summary> /// Gets the bounding box of the mesh transformed first into world space, and then into the local space of another affine transform. /// </summary> /// <param name="shapeTransform">Transform to use to put the shape into world space.</param> /// <param name="spaceTransform">Used as the frame of reference to compute the bounding box. /// In effect, the shape is transformed by the inverse of the space transform to compute its bounding box in local space.</param> /// <param name="boundingBox">Bounding box in the local space.</param> public void GetLocalBoundingBox(ref RigidTransform shapeTransform, ref AffineTransform spaceTransform, out BoundingBox boundingBox) { #if !WINDOWS boundingBox = new BoundingBox(); #endif //TODO: This method peforms quite a few sqrts because the collision margin can get scaled, and so cannot be applied as a final step. //There should be a better way to do this. //Additionally, this bounding box is not consistent in all cases with the post-add version. Adding the collision margin at the end can //slightly overestimate the size of a margin expanded shape at the corners, which is fine (and actually important for the box-box special case). //Move forward into convex's space, backwards into the new space's local space. AffineTransform transform; AffineTransform.Invert(ref spaceTransform, out transform); AffineTransform.Multiply(ref shapeTransform, ref transform, out transform); GetBoundingBox(ref transform.LinearTransform, out boundingBox); boundingBox.Max.X += transform.Translation.X; boundingBox.Max.Y += transform.Translation.Y; boundingBox.Max.Z += transform.Translation.Z; boundingBox.Min.X += transform.Translation.X; boundingBox.Min.Y += transform.Translation.Y; boundingBox.Min.Z += transform.Translation.Z; }
/// <summary> /// Precomputes the transform to bring triangles from their native local space to the local space of the convex. /// </summary> /// <param name="convexInverseWorldTransform">Inverse of the world transform of the convex shape.</param> /// <param name="fromMeshLocalToConvexLocal">Transform to apply to native local triangles to bring them into the local space of the convex.</param> protected override void PrecomputeTriangleTransform(ref AffineTransform convexInverseWorldTransform, out AffineTransform fromMeshLocalToConvexLocal) { //InstancedMeshShapes don't have a shape-level transform. The instance transform is all there is. AffineTransform.Multiply(ref mesh.worldTransform, ref convexInverseWorldTransform, out fromMeshLocalToConvexLocal); }
/// <summary> /// Precomputes the transform to bring triangles from their native local space to the local space of the convex. /// </summary> /// <param name="convexInverseWorldTransform">Inverse of the world transform of the convex shape.</param> /// <param name="fromMeshLocalToConvexLocal">Transform to apply to native local triangles to bring them into the local space of the convex.</param> protected override void PrecomputeTriangleTransform(ref AffineTransform convexInverseWorldTransform, out AffineTransform fromMeshLocalToConvexLocal) { AffineTransform.Multiply(ref terrain.worldTransform, ref convexInverseWorldTransform, out fromMeshLocalToConvexLocal); }