func fire() { var mass m.Real = 1.5 var radius m.Real = 0.2 // create a test sphere to render bullet := CreateSphere(float32(radius), 16, 16) bullet.Shader = colorShader bullet.Color = mgl.Vec4{0.2, 0.2, 1.0, 1.0} // create the collision box for the the bullet bulletCollider := cubez.NewCollisionSphere(nil, radius) bulletCollider.Body.Position = m.Vector3{0.0, 1.5, 20.0} var cubeInertia m.Matrix3 var coeff m.Real = 0.4 * mass * radius * radius cubeInertia.SetInertiaTensorCoeffs(coeff, coeff, coeff, 0.0, 0.0, 0.0) bulletCollider.GetBody().SetInertiaTensor(&cubeInertia) bulletCollider.Body.SetMass(mass) bulletCollider.Body.Velocity = m.Vector3{0.0, 0.0, -40.0} bulletCollider.Body.Acceleration = m.Vector3{0.0, -2.5, 0.0} bulletCollider.Body.CalculateDerivedData() bulletCollider.CalculateDerivedData() e := NewEntity(bullet, bulletCollider) bullets = append(bullets, e) }
func fire() { const cubesToMake = 4 var offset float32 = 0.0 if len(cubes) > 0 && (len(cubes)/cubesToMake)%2 >= 1 { offset = 0.75 } for i := 0; i < cubesToMake; i++ { e := new(Entity) e.Node = CreateCube(-0.5, -0.5, -0.5, 0.5, 0.5, 0.5) e.Node.Shader = diffuseShader e.Node.Color = mgl.Vec4{1.0, 1.0, 1.0, 1.0} e.Node.Location = mgl.Vec3{float32(i*2.0-cubesToMake/2) - 0.5 + offset, 10.0, 0.0} e.Node.Tex0 = crateTexture // create the collision box for the the cube cubeCollider := cubez.NewCollisionCube(nil, m.Vector3{0.5, 0.5, 0.5}) cubeCollider.Body.Position = m.Vector3{m.Real(i*2.0-cubesToMake/2) - 0.5 + m.Real(offset), 10.0, 0.0} cubeCollider.Body.SetMass(8.0) cubeCollider.Body.CanSleep = true var cubeInertia m.Matrix3 cubeInertia.SetBlockInertiaTensor(&cubeCollider.HalfSize, 8.0) cubeCollider.Body.SetInertiaTensor(&cubeInertia) cubeCollider.Body.CalculateDerivedData() cubeCollider.CalculateDerivedData() e.Collider = cubeCollider cubes = append(cubes, e) } }
// calculateFrictionImpulse calculates the impulse needed to resolve this contact, // given that the contact has a non-zero coefficient of friction. func (c *Contact) calculateFrictionImpulse(inverseInertiaTensors [2]m.Matrix3) (impulseContact m.Vector3) { inverseMass := c.Bodies[0].GetInverseMass() // the equivalent of a cross product in matrices is multiplication // by a skew symmetric matrix - we build the matrix for converting // between linear and angular quantities. var impulseToTorque m.Matrix3 setSkewSymmetric(&impulseToTorque, &c.relativeContactPosition[0]) // build the matrix to convert contact impulse to change in velocity in // world coordinates deltaVelWorld := impulseToTorque.MulMatrix3(&inverseInertiaTensors[0]) deltaVelWorld = deltaVelWorld.MulMatrix3(&impulseToTorque) deltaVelWorld.MulWith(-1.0) // check to see if we need to add the second body's data if c.Bodies[1] != nil { // set the cross product matrix setSkewSymmetric(&impulseToTorque, &c.relativeContactPosition[1]) // calculate the velocity change matrix deltaVelWorld2 := impulseToTorque.MulMatrix3(&inverseInertiaTensors[1]) deltaVelWorld2 = deltaVelWorld2.MulMatrix3(&impulseToTorque) deltaVelWorld2.MulWith(-1.0) // add to the total delta velocity deltaVelWorld.Add(&deltaVelWorld2) // add to the inverse mass inverseMass += c.Bodies[1].GetInverseMass() } // do a change of basis to convert into contact coordinates deltaVelocity := c.contactToWorld.Transpose() deltaVelocity = deltaVelocity.MulMatrix3(&deltaVelWorld) deltaVelocity = deltaVelocity.MulMatrix3(&c.contactToWorld) // add in the linear velocity change deltaVelocity[0] += inverseMass deltaVelocity[4] += inverseMass deltaVelocity[8] += inverseMass // invert to get the impulse needed per unit velocity impulseMatrix := deltaVelocity.Invert() // find the target velocities to kill velKill := m.Vector3{ c.desiredDeltaVelocity, -c.contactVelocity[1], -c.contactVelocity[2], } // find the impulse to kill target velocities impulseContact = impulseMatrix.MulVector3(&velKill) // check for exceeding friction planarImpulse := m.RealSqrt(impulseContact[1]*impulseContact[1] + impulseContact[2]*impulseContact[2]) if planarImpulse > impulseContact[0]*c.Friction { // we need to use dynamic friction impulseContact[1] /= planarImpulse impulseContact[2] /= planarImpulse impulseContact[0] = deltaVelocity[0] + deltaVelocity[3]*c.Friction*impulseContact[1] + deltaVelocity[6]*c.Friction*impulseContact[2] impulseContact[0] = c.desiredDeltaVelocity / impulseContact[0] impulseContact[1] *= c.Friction * impulseContact[0] impulseContact[2] *= c.Friction * impulseContact[0] } return }
func main() { app = NewApp() app.InitGraphics("Ballistic", 800, 600) app.SetKeyCallback(keyCallback) app.OnRender = renderCallback app.OnUpdate = updateCallback defer app.Terminate() // compile the shaders var err error colorShader, err = LoadShaderProgram(DiffuseColorVertShader, DiffuseColorFragShader) if err != nil { panic("Failed to compile the shader! " + err.Error()) } // create the ground plane groundPlane = cubez.NewCollisionPlane(m.Vector3{0.0, 1.0, 0.0}, 0.0) // make a ground plane to draw ground = CreatePlaneXZ(-500.0, 500.0, 500.0, -500.0, 1.0) ground.Shader = colorShader ground.Color = mgl.Vec4{0.6, 0.6, 0.6, 1.0} // create a test cube to render cubeNode := CreateCube(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0) cubeNode.Shader = colorShader cubeNode.Color = mgl.Vec4{1.0, 0.0, 0.0, 1.0} // create the collision box for the the cube var cubeMass m.Real = 8.0 var cubeInertia m.Matrix3 cubeCollider := cubez.NewCollisionCube(nil, m.Vector3{1.0, 1.0, 1.0}) cubeCollider.Body.Position = m.Vector3{0.0, 5.0, 0.0} cubeCollider.Body.SetMass(cubeMass) cubeInertia.SetBlockInertiaTensor(&cubeCollider.HalfSize, cubeMass) cubeCollider.Body.SetInertiaTensor(&cubeInertia) cubeCollider.Body.CalculateDerivedData() cubeCollider.CalculateDerivedData() // make the entity out of the renerable and collider cube = NewEntity(cubeNode, cubeCollider) // make a slice of entities for bullets bullets = make([]*Entity, 0, 16) // make the backboard to bound the bullets off of backboardNode := CreateCube(-0.5, -2.0, -0.25, 0.5, 2.0, 0.25) backboardNode.Shader = colorShader backboardNode.Color = mgl.Vec4{0.25, 0.2, 0.2, 1.0} backboardCollider := cubez.NewCollisionCube(nil, m.Vector3{0.5, 2.0, 0.25}) backboardCollider.Body.Position = m.Vector3{0.0, 2.0, -10.0} backboardCollider.Body.SetInfiniteMass() backboardCollider.Body.CalculateDerivedData() backboardCollider.CalculateDerivedData() SetGlVector3(&backboardNode.Location, &backboardCollider.Body.Position) // make the backboard entity backboard = NewEntity(backboardNode, backboardCollider) // setup the camera app.CameraPos = mgl.Vec3{-3.0, 3.0, 15.0} app.CameraRotation = mgl.QuatLookAtV( mgl.Vec3{-3.0, 3.0, 15.0}, mgl.Vec3{0.0, 1.0, 0.0}, mgl.Vec3{0.0, 1.0, 0.0}) gl.Enable(gl.DEPTH_TEST) app.RenderLoop() }
// SetInertiaTensor sets the InverseInertiaTensor member of the RigidBody // by calculating the inverse of the matrix supplied. func (body *RigidBody) SetInertiaTensor(m *m.Matrix3) { body.InverseInertiaTensor = m.Invert() }