local mesh = require 'honey.mesh' local glm = require 'honey.glm' local Vec3 = glm.Vec3 local ode = honey.ode local module = {} setmetatable(module, {__index=_G}) setfenv(1, module) local function loadTriMesh(space, filename) local attrib, shapes, _ = honey.tinyobj.parse_obj( filename, honey.tinyobj.FLAG_TRIANGULATE ) local vertices, indices = mesh.loadShape(shapes[1], attrib) trimeshdata = ode.GeomTriMeshDataCreate() ode.GeomTriMeshDataBuild(trimeshdata, vertices, indices) return ode.CreateTriMesh(space, trimeshdata) end --===== collision space =====-- local function createGeom(self, id, collision) local geom if collision.class == "sphere" then geom = ode.CreateSphere(self.space, collision.radius) elseif collision.class == "capsule" then geom = ode.CreateCapsule(self.space, collision.radius, collision.length) elseif collision.class == "plane" then local node = self.db:getComponent(id, "node") local m = node.matrix local normal = node.matrix:mulv3(Vec3{0,1,0}):normalize() local position = Vec3{m[1][4], m[2][4], m[3][4]} print(position) 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) elseif collision.class == "trimesh" then geom = loadTriMesh(self.space, collision.filename) end ode.GeomSetCategoryBits(geom, collision.category or 1) ode.GeomSetCollideBits(geom, collision.collide or 0xffffffff) ode.GeomSetData(geom, id) collision._geom = geom collision._gc = honey.util.gc_canary(function() print("release geom for id"..id) ode.GeomDestroy(geom) end) end local function isPlaceable(collision) if collision.class == "ray" then return true elseif collision.class == "trimesh" then return true end return false end system = function(params) local db = params.db local space = params.space return { db=db, space=space, priority=0, update = function(self, dt) local query = self.db:queryComponent("collision") for id, collision in pairs(query) do if not collision._geom then 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 } end return module