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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
local gl = honey.gl
local glfw = honey.glfw
local ode = honey.ode
local ecs = require 'honey.ecs.ecs'
local collision = require 'honey.ecs.collision'
local node = require 'honey.ecs.node'
local image = require 'honey.asset.image'
local shader = require 'honey.asset.shader'
local mesh = require 'honey.asset.mesh'
local glm = require 'honey.glm'
local Vec3 = glm.Vec3
local Mat4 = glm.Mat4
local module = {}
setmetatable(module, {__index=_G})
setfenv(1, module)
local function drawMesh(program, uniforms, matrices, vao, count)
gl.UseProgram(program)
-- bind matrices
shader.configure(program, {
matrix={
model = matrices.model,
view = matrices.view,
projection = matrices.projection,
},
})
-- bind textures
local offset = 0
for name, tbl in pairs(uniforms.textures or {}) do
local tex = image.get(tbl.filename)
gl.BindTexture(gl.TEXTURE_2D + offset, tex)
shader.setInt(program, name, offset)
offset = offset+1
end
-- configure additional uniforms
shader.configure(program, uniforms)
-- render mesh
gl.BindVertexArray(vao)
gl.DrawElements(gl.TRIANGLES, count, gl.UNSIGNED_INT, 0)
end
local function drawMeshes(db, view, projection)
local meshes = db:queryComponent("renderMesh")
for id, tbl in pairs(meshes) do
-- get model matrix
local node = db:getComponent(id, "node")
local model = (node and node._matrix) or Mat4():identity()
-- get shader program
local program = shader.get(tbl.shader)
-- get mesh
local vao, count = mesh.get(tbl.mesh.filename, tbl.mesh.index)
-- draw c:
drawMesh(program, tbl.uniforms or {}, {view=view, model=model, projection=projection}, vao, count)
end
end
local function drawGeoms(db, view, projection)
-- draw wireframes
gl.Enable(gl.CULL_FACE)
gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
gl.LineWidth(1)
-- shader program for all geoms
local program = shader.get{ vertex="builtin.basic3d.vert", fragment="builtin.color.frag" }
local uniforms = {
vec3 = {
color = Vec3{ 1, 0, 1 },
},
}
local query = db:queryComponent("collision")
for id, tbl in pairs(query) do
-- compute model matrix
local m = Mat4():identity()
m[1][4], m[2][4], m[3][4] = ode.GeomGetPosition(tbl._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] = ode.GeomGetRotation(tbl._geom)
local matrices = {
view=view,
projection=projection,
model=m,
}
-- get the mesh
if tbl.class == "sphere" then
m:scale(Vec3{tbl.radius, tbl.radius, tbl.radius})
local vao, count = mesh.get("builtin.hemisphere", 1)
drawMesh(program, uniforms, matrices, vao, count)
m:rotateX(math.pi)
drawMesh(program, uniforms, matrices, vao, count)
elseif tbl.class == "box" then
m:scale(Vec3{tbl.lx, tbl.ly, tbl.lz})
local vao, count = mesh.get("builtin.cube", 1)
drawMesh(program, uniforms, matrices, vao, count)
elseif tbl.class == "capsule" then
m:scale(Vec3{tbl.radius, tbl.length/2, tbl.radius})
local vao, count = mesh.get("builtin.tube", 1)
drawMesh(program, uniforms, matrices, vao, count)
m:scale(Vec3{1, 2*tbl.radius/tbl.length, 1})
:translate(Vec3{0, tbl.length/2, 0})
vao, count = mesh.get("builtin.hemisphere", 1)
drawMesh(program, uniforms, matrices, vao, count)
m:translate(Vec3{0, -tbl.length, 0})
:rotateX(math.pi)
drawMesh(program, uniforms, matrices, vao, count)
elseif tbl.class == "ray" then
m:scale(Vec3{0.001, 0.001, tbl.length})
local vao, count = mesh.get("builtin.cube", 1)
drawMesh(program, uniforms, matrices, vao, count)
end
end
-- switch out of wireframe mode
gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
end
local render = ecs.System("render", function(db, dt, p)
for id, camera in pairs(db:queryComponent("camera")) do
-- get camera's view and projection matrices
local projection = camera.projection
local view = Mat4()
local node = db:getComponent(id, "node")
if node then
honey.glm.mat4_inv(node._matrix.data, view.data)
else
view:identity()
end
-- optionally draw collision geoms
if p.drawGeoms then
drawGeoms(db, view, projection)
end
-- render all scene meshes
drawMeshes(db, view, projection)
end
end)
render:addDependencies(node.system)
render:addDependencies(collision.system)
system = {render}
return module
|