Пример #1
0
 public RegularGridBuilder(Vector3 spacing, Vector3 origin, BodyInertia localInertia, TypedIndex shapeIndex = new TypedIndex())
 {
     Spacing      = spacing;
     Origin       = origin;
     LocalInertia = localInertia;
     ShapeIndex   = shapeIndex;
 }
Пример #2
0
        public override void ProcessBlock(float deltaTime, BlockAccessor block)
        {
            var entities     = block.GetEntityData();
            var collider     = block.GetSharedComponentData <MeshCollider>();
            var hasRigidBody = block.TryGetComponentData(out Span <RigidBody> rbs);
            var hasScale     = block.TryGetComponentData(out Span <Scale> scales);

            Vector3 defaultScale = Vector3.One;

            for (int i = 0; i < block.length; i++)
            {
                Vector3 scale = defaultScale;
                if (hasScale)
                {
                    scale = new Vector3(scales[i].value.x, scales[i].value.y, scales[i].value.z);
                }
                Mesh mesh = new Mesh(collider.GetTriangles(), scale, PhysicsSystem.BufferPool);

                TypedIndex shapeIdx = PhysicsSystem.Simulation.Shapes.Add(mesh);

                BodyInertia inertia = new BodyInertia();
                if (hasRigidBody)
                {
                    mesh.ComputeOpenInertia(rbs[i].mass, out inertia);
                }

                afterUpdateCommands.AddComponent(entities[i],
                                                 new InternalColliderHandle()
                {
                    inertia  = inertia,
                    shapeIdx = shapeIdx
                });
            }
        }
Пример #3
0
        public override void ProcessBlock(float deltaTime, BlockAccessor block)
        {
            var entities     = block.GetEntityData();
            var colliders    = block.GetReadOnlyComponentData <BoxCollider>();
            var hasRigidBody = block.TryGetComponentData(out Span <RigidBody> rbs);
            var hasScale     = block.TryGetComponentData(out Span <Scale> scales);

            vec3 defaultScale = vec3.Ones;

            for (int i = 0; i < block.length; i++)
            {
                vec3 scale = hasScale ? scales[i].value : defaultScale;

                Box box = new Box(colliders[i].width * scale.x, colliders[i].height * scale.y, colliders[i].length * scale.z);

                TypedIndex shapeIdx = PhysicsSystem.Simulation.Shapes.Add(box);

                BodyInertia inertia = new BodyInertia();
                if (hasRigidBody)
                {
                    box.ComputeInertia(rbs[i].mass, out inertia);
                }

                afterUpdateCommands.AddComponent(entities[i],
                                                 new InternalColliderHandle()
                {
                    inertia  = inertia,
                    shapeIdx = shapeIdx
                });
            }
        }
Пример #4
0
        protected override void SetBody(TypedIndex type, float speculativeMargin, BodyInertia inertia, Vector3 offset)
        {
            var physicsSystem = GameObject.CurrentScene.GetOrCreateSystem <PhysicsSystem>();

            if (_voxelStatic.Exists)
            {
                physicsSystem.RemoveStatic(_voxelStatic);
            }
            var transformedOffset = Vector3.Transform(offset, GameObject.Transform.WorldOrientation);

            _voxelStatic = physicsSystem.AddStatic(new StaticDescription(GameObject.Transform.WorldPosition + transformedOffset, new CollidableDescription(type, speculativeMargin)), this);
        }
Пример #5
0
        protected override void OnAttach()
        {
            base.OnAttach();

            rigidBody = Entity.Get <RigidbodyComponent>();

            BodyInertia interia = new BodyInertia {
                InverseMass = 1f / Mass
            };

            rigidBody.GetBodyReference().SetLocalInertia(interia);

            ref var character = ref Simulation.AllocateCharacter(rigidBody.BodyHandle);
Пример #6
0
 public void ComputeAnalyticInertia(float mass, out BodyInertia inertia)
 {
     Box.ComputeInertia(mass, out inertia);
 }
Пример #7
0
 public override void GetShapeInteria(float mass, out BodyInertia inertia)
 {
     ((Cylinder)InternalShape).ComputeInertia(mass, out inertia);
 }
Пример #8
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(25, 4, 40);
            camera.Yaw      = 0;
            Simulation      = Simulation.Create(BufferPool, new TestCallbacks());

            Simulation.PoseIntegrator.Gravity = new Vector3(0, -10, 0);

            var shapeA      = new Box(.75f, 1, .5f);
            var shapeIndexA = Simulation.Shapes.Add(shapeA);
            var collidableA = new CollidableDescription(shapeIndexA, 0.1f);
            var shapeB      = new Box(.75f, 1, .5f);
            var shapeIndexB = Simulation.Shapes.Add(shapeB);
            var collidableB = new CollidableDescription(shapeIndexB, 0.1f);
            var activity    = new BodyActivityDescription(0.01f);

            shapeA.ComputeInertia(1, out var inertiaA);
            shapeA.ComputeInertia(1, out var inertiaB);
            var nextX = -10f;

            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularHinge {
                    LocalHingeAxisA = new Vector3(0, 1, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new Hinge
                {
                    LocalOffsetA    = new Vector3(0, 1, 0),
                    LocalHingeAxisA = new Vector3(0, 1, 0),
                    LocalOffsetB    = new Vector3(0, -1, 0),
                    LocalHingeAxisB = new Vector3(0, 1, 0),
                    SpringSettings  = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularSwivelHinge {
                    LocalSwivelAxisA = new Vector3(1, 0, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new SwingLimit {
                    AxisLocalA = new Vector3(0, 1, 0), AxisLocalB = new Vector3(0, 1, 0), MaximumSwingAngle = MathHelper.PiOver2, SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new SwivelHinge
                {
                    LocalOffsetA     = new Vector3(0, 1, 0),
                    LocalSwivelAxisA = new Vector3(1, 0, 0),
                    LocalOffsetB     = new Vector3(0, -1, 0),
                    LocalHingeAxisB  = new Vector3(0, 1, 0),
                    SpringSettings   = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new SwingLimit {
                    AxisLocalA = new Vector3(0, 1, 0), AxisLocalB = new Vector3(0, 1, 0), MaximumSwingAngle = MathHelper.PiOver2, SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new TwistServo
                {
                    LocalBasisA    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    LocalBasisB    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    TargetAngle    = MathHelper.PiOver4,
                    SpringSettings = new SpringSettings(30, 1),
                    ServoSettings  = new ServoSettings(float.MaxValue, 0, float.MaxValue)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new TwistLimit
                {
                    LocalBasisA    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    LocalBasisB    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    MinimumAngle   = MathHelper.Pi * -0.5f,
                    MaximumAngle   = MathHelper.Pi * 0.95f,
                    SpringSettings = new SpringSettings(30, 1),
                });
                Simulation.Solver.Add(a, b, new AngularHinge {
                    LocalHingeAxisA = new Vector3(0, 1, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new TwistMotor
                {
                    LocalAxisA     = new Vector3(0, 1, 0),
                    LocalAxisB     = new Vector3(0, 1, 0),
                    TargetVelocity = MathHelper.Pi * 2,
                    Settings       = new MotorSettings(float.MaxValue, 0.1f)
                });
                Simulation.Solver.Add(a, b, new AngularHinge {
                    LocalHingeAxisA = new Vector3(0, 1, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularServo
                {
                    TargetRelativeRotationLocalA = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), MathHelper.PiOver2),
                    ServoSettings  = new ServoSettings(float.MaxValue, 0, 12f),
                    SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularMotor {
                    TargetVelocityLocalA = new Vector3(0, 1, 0), Settings = new MotorSettings(15, 0.0001f)
                });
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity);
                var bDescription = BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity);
                //aDescription.Velocity.Angular = new Vector3(0, 0, 5);
                var a = Simulation.Bodies.Add(aDescription);
                var b = Simulation.Bodies.Add(bDescription);
                Simulation.Solver.Add(a, b, new Weld {
                    LocalOffset = new Vector3(0, 2, 0), LocalOrientation = Quaternion.Identity, SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x      = GetNextPosition(ref nextX);
                var sphere = new Sphere(0.125f);
                //Treat each vertex as a point mass that cannot rotate.
                var sphereInertia = new BodyInertia {
                    InverseMass = 1
                };
                var sphereCollidable = new CollidableDescription(Simulation.Shapes.Add(sphere), 0.1f);
                var a                   = new Vector3(x, 3, 0);
                var b                   = new Vector3(x, 4, 0);
                var c                   = new Vector3(x, 3, 1);
                var d                   = new Vector3(x + 1, 3, 0);
                var aDescription        = BodyDescription.CreateDynamic(a, sphereInertia, sphereCollidable, activity);
                var bDescription        = BodyDescription.CreateDynamic(b, sphereInertia, sphereCollidable, activity);
                var cDescription        = BodyDescription.CreateDynamic(c, sphereInertia, sphereCollidable, activity);
                var dDescription        = BodyDescription.CreateDynamic(d, sphereInertia, sphereCollidable, activity);
                var aHandle             = Simulation.Bodies.Add(aDescription);
                var bHandle             = Simulation.Bodies.Add(bDescription);
                var cHandle             = Simulation.Bodies.Add(cDescription);
                var dHandle             = Simulation.Bodies.Add(dDescription);
                var distanceSpringiness = new SpringSettings(3f, 1);
                Simulation.Solver.Add(aHandle, bHandle, new CenterDistanceConstraint(Vector3.Distance(a, b), distanceSpringiness));
                Simulation.Solver.Add(aHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(a, c), distanceSpringiness));
                Simulation.Solver.Add(aHandle, dHandle, new CenterDistanceConstraint(Vector3.Distance(a, d), distanceSpringiness));
                Simulation.Solver.Add(bHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(b, c), distanceSpringiness));
                Simulation.Solver.Add(bHandle, dHandle, new CenterDistanceConstraint(Vector3.Distance(b, d), distanceSpringiness));
                Simulation.Solver.Add(cHandle, dHandle, new CenterDistanceConstraint(Vector3.Distance(c, d), distanceSpringiness));
                Simulation.Solver.Add(aHandle, bHandle, cHandle, dHandle, new VolumeConstraint(a, b, c, d, new SpringSettings(30, 1)));
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity);
                var bDescription = BodyDescription.CreateDynamic(new Vector3(x, 6, 0), inertiaB, collidableB, activity);
                var a            = Simulation.Bodies.Add(aDescription);
                var b            = Simulation.Bodies.Add(bDescription);
                Simulation.Solver.Add(a, b, new DistanceServo(new Vector3(0, 0.55f, 0), new Vector3(0, -0.55f, 0), 1.9f, new SpringSettings(30, 1), ServoSettings.Default));
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity);
                var bDescription = BodyDescription.CreateDynamic(new Vector3(x, 6, 0), inertiaB, collidableB, activity);
                var a            = Simulation.Bodies.Add(aDescription);
                var b            = Simulation.Bodies.Add(bDescription);
                Simulation.Solver.Add(a, b, new DistanceLimit(new Vector3(0, 0.55f, 0), new Vector3(0, -0.55f, 0), 1f, 3, new SpringSettings(30, 1)));
            }
            {
                var x      = GetNextPosition(ref nextX);
                var sphere = new Sphere(0.125f);
                //Treat each vertex as a point mass that cannot rotate.
                var sphereInertia = new BodyInertia {
                    InverseMass = 1
                };
                var sphereCollidable = new CollidableDescription(Simulation.Shapes.Add(sphere), 0.1f);
                var a                   = new Vector3(x, 3, 0);
                var b                   = new Vector3(x, 4, 0);
                var c                   = new Vector3(x + 1, 3, 0);
                var aDescription        = BodyDescription.CreateDynamic(a, sphereInertia, sphereCollidable, activity);
                var bDescription        = BodyDescription.CreateDynamic(b, sphereInertia, sphereCollidable, activity);
                var cDescription        = BodyDescription.CreateDynamic(c, sphereInertia, sphereCollidable, activity);
                var aHandle             = Simulation.Bodies.Add(aDescription);
                var bHandle             = Simulation.Bodies.Add(bDescription);
                var cHandle             = Simulation.Bodies.Add(cDescription);
                var distanceSpringiness = new SpringSettings(3f, 1);
                Simulation.Solver.Add(aHandle, bHandle, new CenterDistanceConstraint(Vector3.Distance(a, b), distanceSpringiness));
                Simulation.Solver.Add(aHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(a, c), distanceSpringiness));
                Simulation.Solver.Add(bHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(b, c), distanceSpringiness));
                Simulation.Solver.Add(aHandle, bHandle, cHandle, new AreaConstraint(a, b, c, new SpringSettings(30, 1)));
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), default, collidableA, activity);
Пример #9
0
 internal CompoundPhysicsMesh(ICompoundShape shape, TypedIndex meshIndex, BodyInertia inertia)
 {
     this.CompoundShape = shape;
     this.MeshIndex     = meshIndex;
     this.Inertia       = inertia;
 }
Пример #10
0
 public abstract void GetShapeInteria(float mass, out BodyInertia inertia);
Пример #11
0
        private PhyObject CreateVanilla(ObjectState state, CollidableDescription collidableDescription, BodyInertia bodyInertia)
        {
            PhyObject phy;

            if (state.mass != 0)
            {
                BodyDescription boxDescription = BodyDescription.CreateDynamic(state.position, bodyInertia,
                                                                               collidableDescription,
                                                                               new BodyActivityDescription(0.01f));

                boxDescription.Pose = new RigidPose(state.position, state.quaternion);
                var bodyHandle = Simulation.Bodies.Add(boxDescription);



                phy = SetUpPhyObject(bodyHandle, state);
                objectsHandlers.Add(bodyHandle, phy);
            }
            else
            {
                StaticDescription description = new StaticDescription(state.position, state.quaternion, collidableDescription);
                StaticHandle      handle      = Simulation.Statics.Add(description);
                //collidableMaterials.Allocate(handle) = new SimpleMaterial { FrictionCoefficient = 1, MaximumRecoveryVelocity = float.MaxValue, SpringSettings = new SpringSettings(1f, 1f) };
                phy = SetUpPhyObject(handle, state);
                staticObjectsHandlers.Add(handle, (StaticPhyObject)phy);
                //objectsHandlers.Add(handle,phy);
            }


            return(phy);
        }
Пример #12
0
 public override void GetShapeInteria(float mass, out BodyInertia inertia)
 {
     ((Mesh)InternalShape).ComputeClosedInertia(mass, out inertia);
 }
Пример #13
0
            public void ComputeAnalyticInertia(float mass, out BodyInertia inertia)
            {
                //Computing the inertia of a tetrahedron requires integrating across its volume.
                //While it's possible to do so directly given arbitrary plane equations, it's more convenient to integrate over a normalized tetrahedron with coordinates
                //at (0,0,0), (1,0,0), (0,1,0), and (0,0,1). The integration location can be transformed back to the original frame of reference using the tetrahedral edges.
                //That is, (1,0,0) in normalized space transforms to B-A in world space.
                //To make that explicit, we have an equation:
                // [1,0,0]               [ B - A ]
                // [0,1,0] * Transform = [ C - A ]
                // [0,0,1]               [ D - A ]
                //(Note that you could consider this to be an affine transform with a translation equal to A.)

                //Since the normalized edge directions compose the identity matrix, the transform is just the edge directions.
                //So, given function f that computes a point's contribution to the inertia tensor, the inertia tensor of the normalized tetrahedron with uniform unit density is:
                //Integrate[Integrate[Integrate[f[{i, j, k}], {k, 0, 1-i-j}], {j, 0, 1-i}], {i, 0, 1}];
                //Note the integration bounds- they are a result of the simple shape of the normalized tetrahedron making the plane equations easier to deal with.
                //Now, to integrate over the true tetrahedron's shape, the normalized coordinates are transformed to world coordinates:
                //Integrate[Integrate[Integrate[f[{i, j, k}.Transform + A] * Abs[Det[Transform]], {k, 0, 1-i-j}], {j, 0, 1-i}], {i, 0, 1}];

                //One key difference is the inclusion of the transform's jacobian's determinant, which in this case is just the volume of the tetrahedron times six.
                //For a geometric intuition for why that exists, consider that the normalized integration covers a tetrahedron with a volume of 1/6. The world space tetrahedron
                //has a volume of Abs[Det[Transform]]/6. So, the volume changes by a factor of exactly Abs[Det[Transform]].
                //That term compensates for the difference in integration domain.
                //It's also constant over the integration, so you can just pull it out.
                //Similarly, if you had a non-unit uniform density, you would multiply the integration by it too.

                //So, putting that together and assuming the scaling term is pulled out, here's a chunk of code you can plop into wolfram cloud and whatnot to recreate the results:
                //f[{x_, y_, z_}] := {{y^2 + z^2, -x * y, -x * z}, {-x * y, x^2 + z^2, -y * z}, {-x * z, -y * z, x^2 + y^2}}
                //a = { AX, AY, AZ};
                //b = { BX, BY, BZ};
                //c = { CX, CY, CZ};
                //d = { DX, DY, DZ};
                //ab = b - a;
                //ac = c - a;
                //ad = d - a;
                //A = { ab, ac, ad};
                //Integrate[Integrate[Integrate[f[{ i, j, k}.A + a], {k, 0, 1-i-j}], {j, 0, 1-i}],{i, 0, 1}]
                inertia.InverseMass = 1f / mass;
                var ab = B - A;
                var ac = C - A;
                var ad = D - A;
                //Revisiting the determinant, note that:
                //density * abs(determinant) = density * volume * 6 = mass * 6
                //So there's no need to actually compute the determinant/volume since we were given the mass directly.
                var          diagonalScaling = mass * (6f / 60f);
                Symmetric3x3 inertiaTensor;

                inertiaTensor.XX = diagonalScaling * (
                    A.Y * A.Y + A.Z * A.Z + B.Y * B.Y + B.Z * B.Z + C.Y * C.Y + C.Z * C.Z + D.Y * D.Y + D.Z * D.Z +
                    B.Y * C.Y + B.Z * C.Z +
                    (B.Y + C.Y) * D.Y + (B.Z + C.Z) * D.Z +
                    A.Y * (B.Y + C.Y + D.Y) + A.Z * (B.Z + C.Z + D.Z));
                inertiaTensor.YY = diagonalScaling * (
                    A.X * A.X + A.Z * A.Z + B.X * B.X + B.Z * B.Z + C.X * C.X + C.Z * C.Z + D.X * D.X + D.Z * D.Z +
                    B.X * C.X + B.Z * C.Z +
                    (B.X + C.X) * D.X + (B.Z + C.Z) * D.Z +
                    A.X * (B.X + C.X + D.X) + A.Z * (B.Z + C.Z + D.Z));
                inertiaTensor.ZZ = diagonalScaling * (
                    A.X * A.X + A.Y * A.Y + B.X * B.X + B.Y * B.Y + C.X * C.X + C.Y * C.Y + D.X * D.X + D.Y * D.Y +
                    B.X * C.X + B.Y * C.Y +
                    (B.X + C.X) * D.X + (B.Y + C.Y) * D.Y +
                    A.X * (B.X + C.X + D.X) + A.Y * (B.Y + C.Y + D.Y));
                var offScaling = mass * (6f / 120f);

                inertiaTensor.YX = offScaling * (
                    -2 * B.X * B.Y - 2 * C.X * C.Y -
                    B.Y * C.X - B.X * C.Y - B.Y * D.X - C.Y * D.X -
                    A.Y * (B.X + C.X + D.X) - (B.X + C.X + 2 * D.X) * D.Y - A.X * (2 * A.Y + B.Y + C.Y + D.Y));
                inertiaTensor.ZX = offScaling * (
                    -2 * B.X * B.Z - 2 * C.X * C.Z -
                    B.Z * C.X - B.X * C.Z - B.Z * D.X - C.Z * D.X -
                    A.Z * (B.X + C.X + D.X) - (B.X + C.X + 2 * D.X) * D.Z - A.X * (2 * A.Z + B.Z + C.Z + D.Z));
                inertiaTensor.ZY = offScaling * (
                    -2 * B.Y * B.Z - 2 * C.Y * C.Z -
                    B.Z * C.Y - B.Y * C.Z - B.Z * D.Y - C.Z * D.Y -
                    A.Z * (B.Y + C.Y + D.Y) - (B.Y + C.Y + 2 * D.Y) * D.Z - A.Y * (2 * A.Z + B.Z + C.Z + D.Z));
                //TODO: Note that the above implementation isn't exactly optimal. Assuming for now that the performance isn't going to be relevant.
                //That could change given certain convex hull use cases, but in that situation you should probably just jump to vectorizing over multiple tetrahedra at a time.
                //(Plus some basic term caching.)
                Symmetric3x3.Invert(inertiaTensor, out inertia.InverseInertiaTensor);
            }