diff options
author | sanine <sanine.not@pm.me> | 2023-05-10 23:59:04 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-05-10 23:59:04 -0500 |
commit | 14195dac1eda9140192ca07003258715b8b0abd3 (patch) | |
tree | bb4e41153363c791d4a9c7948bc85e0d4f77bc98 /honey/ecs | |
parent | 26bfc10ad0e8a355e9b02946dd31642f49a6ec60 (diff) |
implement basic floating-ray character controller
Diffstat (limited to 'honey/ecs')
-rw-r--r-- | honey/ecs/collision.lua | 35 | ||||
-rw-r--r-- | honey/ecs/physics.lua | 83 |
2 files changed, 87 insertions, 31 deletions
diff --git a/honey/ecs/collision.lua b/honey/ecs/collision.lua index 5c0452b..4c8af5b 100644 --- a/honey/ecs/collision.lua +++ b/honey/ecs/collision.lua @@ -25,8 +25,12 @@ local function createGeom(self, id, collision) local d = normal:dot(position) print(normal, d) geom = ode.CreatePlane(self.space, normal[1], normal[2], normal[3], d) + elseif collision.class == "ray" then + geom = ode.CreateRay(self.space, collision.length) end + ode.GeomSetCategoryBits(geom, collision.category or 1) + ode.GeomSetCollideBits(geom, collision.collide or 0xffffffff) ode.GeomSetData(geom, id) collision._geom = geom @@ -36,6 +40,15 @@ local function createGeom(self, id, collision) end) end + +local function isPlaceable(collision) + if collision.class == "ray" then + return true + end + return false +end + + system = function(params) local db = params.db local space = params.space @@ -50,6 +63,28 @@ system = function(params) createGeom(self, id, collision) print(id, collision._geom) end + if + not self.db:getComponent(id, "physics") and + isPlaceable(collision) + then + -- no attached physics body, update position & orientation + -- from node transform + local node = self.db:getComponent(id, "node") + local m = node._matrix or node.matrix + local geom = collision._geom + ode.GeomSetPosition( + geom, + m[1][4], + m[2][4], + m[3][4] + ) + ode.GeomSetRotation( + geom, + 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] + ) + end end end } diff --git a/honey/ecs/physics.lua b/honey/ecs/physics.lua index 9b22bd7..2bef336 100644 --- a/honey/ecs/physics.lua +++ b/honey/ecs/physics.lua @@ -4,6 +4,8 @@ local Mat4 = glm.Mat4 local Quaternion = glm.Quaternion local ode = honey.ode +local script = require 'honey.ecs.script' + local module = {} setmetatable(module, {__index=_G}) setfenv(1, module) @@ -22,13 +24,23 @@ local function createMass(tbl) tbl.radius ) elseif class == "capsule" then - ode.MassSetCapsule( - mass, - tbl.density, - tbl.direction, - tbl.radius, - tbl.length - ) + if tbl.mass then + ode.MassSetCapsuleTotal( + mass, + tbl.mass, + tbl.direction, + tbl.radius, + tbl.length + ) + else + ode.MassSetCapsule( + mass, + tbl.density, + tbl.direction, + tbl.radius, + tbl.length + ) + end end return mass end @@ -92,10 +104,11 @@ local function createPhysicsBody(db, world, id, component) end -local function handleCollision(db, self, other) +local function handleCollision(db, self, other, collision) local handler = db:getComponent(self, "onCollision") if handler then - handler(db, self, other) + h = script.getFunction(handler) + h(db, self, other, collision) end end @@ -104,28 +117,36 @@ local function collide(self, a, b, collision) -- check for collision handlers local idA = ode.GeomGetData(a) local idB = ode.GeomGetData(b) - handleCollision(self.db, idA, idB) - handleCollision(self.db, idB, idA) - - -- set up the joint params - local contact = ode.CreateContact{ surface={ - mode = ode.ContactBounce + ode.ContactSoftCFM, - mu = ode.Infinity, - bounce = 0.90, - bounce_vel = 0.1, - soft_cfm = 0.001, - }} - ode.ContactSetGeom(contact, collision) - -- create the joint - local joint = ode.JointCreateContact( - self.world, - self.contactGroup, - contact - ) - -- attach the two bodies - local bodyA = ode.GeomGetBody(a) - local bodyB = ode.GeomGetBody(b) - ode.JointAttach(joint, bodyA, bodyB) + handleCollision(self.db, idA, idB, collision) + handleCollision(self.db, idB, idA, collision) + + local physicsA = self.db:getComponent(idA, "physics") + local physicsB = self.db:getComponent(idB, "physics") + + local surface = (physicsA and physicsA.surface) or + (physicsB and physicsB.surface) + + if surface then + -- set up the joint params + local contact = ode.CreateContact{ surface={ + mode = ode.ContactBounce + ode.ContactSoftCFM, + mu = ode.Infinity, + bounce = 0.90, + bounce_vel = 0.1, + soft_cfm = 0.001, + }} + ode.ContactSetGeom(contact, collision) + -- create the joint + local joint = ode.JointCreateContact( + self.world, + self.contactGroup, + contact + ) + -- attach the two bodies + local bodyA = ode.GeomGetBody(a) + local bodyB = ode.GeomGetBody(b) + ode.JointAttach(joint, bodyA, bodyB) + end end --===== physics =====-- |