1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
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
|