diff options
-rw-r--r-- | honey/ecs/physics.lua | 147 |
1 files changed, 85 insertions, 62 deletions
diff --git a/honey/ecs/physics.lua b/honey/ecs/physics.lua index eac3846..e2c9b9a 100644 --- a/honey/ecs/physics.lua +++ b/honey/ecs/physics.lua @@ -8,6 +8,89 @@ local module = {} setmetatable(module, {__index=_G}) setfenv(1, module) + +-- create a new mass +local function createMass(tbl) + local mass = ode.MassCreate() + local class = tbl.class + if not class then + -- configure mass manually + elseif class == "sphere" then + ode.MassSetSphere( + mass, + tbl.density, + tbl.radius + ) + elseif class == "capsule" then + ode.MassSetCapsule( + mass, + tbl.density, + tbl.direction, + tbl.radius, + tbl.length + ) + end + return mass +end + + +-- create a new physics body +local function createPhysicsBody(db, world, id, component) + -- initialize the body with garbage collector + print("add component body for "..id) + local body = ode.BodyCreate(world) + component._gc = honey.util.gc_canary(function() + print("releasing component body for " .. id) + ode.BodyDestroy(body) + body = nil + end) + + -- connect the body with a collision geom + local collision = db:getComponent(id, "collision") + if collision then + print(id, collision.class) + ode.GeomSetBody(collision._geom, body) + end + + -- set the mass of the body + ode.BodySetMass(body, createMass(component.mass)) + + -- set the transform of the body + local m = db:getComponent(id, "node").matrix + ode.BodySetPosition( + body, + m[1][4], m[2][4], m[3][4] + ) + ode.BodySetRotation( + body, + m[1][1], m[1][2], m[1][3], + m[2][1], m[2][2], m[2][3], + m[3][1], m[3][2], m[3][3] + ) + + -- set the linear velocity + local vel = component.velocity or Vec3{0,0,0} + ode.BodySetLinearVel( + body, vel[1], vel[2], vel[3] + ) + component.velocity = vel + + -- set the angular velocity + local avel = component.angularVelocity or Vec3{0,0,0} + ode.BodySetAngularVel( + body, avel[1], avel[2], avel[3] + ) + component.angularVelocity = avel + + -- optionally set a maximum angular speed + if component.maxAngularSpeed then + ode.BodySetMaxAngularSpeed(body, component.maxAngularSpeed) + end + + -- put the body into the physics component + component._body = body +end + --===== physics =====-- @@ -29,70 +112,10 @@ system = function(params) end local query = self.db:queryComponent("physics") + -- check for new physics entities for id, physics in pairs(query) do if not physics._body then - print("add physics body for "..id) - local body = ode.BodyCreate(self.world) - physics._gc = honey.util.gc_canary(function() - print("releasing physics body for " .. id) - ode.BodyDestroy(body) - body = nil - end) - - local collision = self.db:getComponent(id, "collision") - if collision then - print(id, collision.class) - ode.GeomSetBody(collision._geom, body) - end - - local mass = ode.MassCreate() - local class = physics.mass.class - if not class then - -- configure mass manually - elseif class == "sphere" then - ode.MassSetSphere( - mass, - physics.mass.density, - physics.mass.radius - ) - elseif class == "capsule" then - ode.MassSetCapsule( - mass, - physics.mass.density, - physics.mass.direction, - physics.mass.radius, - physics.mass.length - ) - end - ode.BodySetMass(body, mass) - local m = self.db:getComponent(id, "node").matrix - ode.BodySetPosition( - body, - m[1][4], m[2][4], m[3][4] - ) - ode.BodySetRotation( - body, - m[1][1], m[1][2], m[1][3], - m[2][1], m[2][2], m[2][3], - m[3][1], m[3][2], m[3][3] - ) - local vel = physics.velocity or Vec3{0,0,0} - ode.BodySetLinearVel( - body, vel[1], vel[2], vel[3] - ) - physics.velocity = vel - - local avel = physics.angularVelocity or Vec3{0,0,0} - ode.BodySetAngularVel( - body, avel[1], avel[2], avel[3] - ) - physics.angularVelocity = avel - - if physics.maxAngularSpeed then - ode.BodySetMaxAngularSpeed(body, physics.maxAngularSpeed) - end - - physics._body = body + createPhysicsBody(self.db, self.world, id, physics) end end |