summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--honey/ecs/physics.lua147
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