summaryrefslogtreecommitdiff
path: root/honey/ecs
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-05-10 23:59:04 -0500
committersanine <sanine.not@pm.me>2023-05-10 23:59:04 -0500
commit14195dac1eda9140192ca07003258715b8b0abd3 (patch)
treebb4e41153363c791d4a9c7948bc85e0d4f77bc98 /honey/ecs
parent26bfc10ad0e8a355e9b02946dd31642f49a6ec60 (diff)
implement basic floating-ray character controller
Diffstat (limited to 'honey/ecs')
-rw-r--r--honey/ecs/collision.lua35
-rw-r--r--honey/ecs/physics.lua83
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 =====--