summaryrefslogtreecommitdiff
path: root/honey/mesh.lua
blob: 12edea96e91c362f9cb6d6bdf3f4a9527ab01a08 (plain)
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
local module = {}
local gl = honey.gl
setmetatable(module, {__index=_G})
setfenv(1, module)


local function printVertex(vertices, i)
	print(string.format(
		"p(%f, %f, %f), n(%f, %f, %f), t(%f, %f)",
		vertices[i+0],
		vertices[i+1],
		vertices[i+2],


		vertices[i+3],
		vertices[i+4],
		vertices[i+5],


		vertices[i+5],
		vertices[i+6]
	))
end


local function insertVertex(vertices, attrib, vertex, debug)
	if debug then print() end
	local pos = 3*vertex.v_idx
	for i=1,3 do
		table.insert(vertices, attrib.vertices[pos+i])
		if debug then print(vertices[#vertices]) end
	end

	local normal = 3*vertex.vn_idx
	for i=1,3 do
		table.insert(vertices, attrib.normals[normal+i])
		if debug then print(vertices[#vertices]) end
	end

	local tex = 2*vertex.vt_idx
	for i=1,2 do
		table.insert(vertices, attrib.texcoords[tex+i])
		if debug then print(vertices[#vertices]) end
	end
	if debug then 
		for i=1,#attrib.texcoords do
			print(i, attrib.texcoords[i])
		end
	end
end


function loadShape(shape, attrib, debug)
	local vertices = {}
	local indices = {}

	local start = shape.face_offset
	local finish = start + shape.length
	for i=start,finish-1 do
		assert(attrib.face_num_verts[i+1] == 3, "non-triangular face!")
		for j=0,2 do
			local vertex = attrib.faces[(3*i) + j + 1]
			insertVertex(vertices, attrib, vertex, debug)
			table.insert(indices, #indices)
		end
	end

	return vertices, indices
end


function loadFile(filename, debug)
	local flags = honey.tinyobj.FLAG_TRIANGULATE
	if debug then print("load file:", filename) end
	local attrib, shapes, materials = honey.tinyobj.parse_obj(filename, flags)
	
	local meshes = {}
	for _, shape in ipairs(shapes) do
		local vertices, indices = loadShape(shape, attrib, debug)
		table.insert(meshes, Mesh(vertices, indices))
	end
	if debug then print("finished file:", filename) end
	return meshes
end


cache = {}
function loadCached(filename, index, debug)
	if not cache[filename] then
		cache[filename] = loadFile(filename, debug)
	end
	return cache[filename][index]
end


Mesh = {}
Mesh.__index = Mesh


function Mesh.new(_, vertices, indices)
	local self = {}
	setmetatable(self, Mesh)

	self.vertexArray = gl.GenVertexArrays()
	self.vertexBuffer = gl.GenBuffers()
	self.elementBuffer = gl.GenBuffers()
	self.vertexCount = #indices

	gl.BindVertexArray(self.vertexArray)
	gl.BindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer)
	gl.BufferData(gl.ARRAY_BUFFER, gl.FLOAT, vertices, gl.STATIC_DRAW)

	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.elementBuffer)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.UNSIGNED_INT, indices, gl.STATIC_DRAW)

	gl.VertexAttribPointer(0, 3, false, 8, 0)
	gl.EnableVertexAttribArray(0)
	gl.VertexAttribPointer(1, 3, false, 8, 3)
	gl.EnableVertexAttribArray(1)
	gl.VertexAttribPointer(2, 2, false, 8, 6)
	gl.EnableVertexAttribArray(2)

	return self
end
setmetatable(Mesh, {__call=Mesh.new})


function Mesh.drawElements(self)
	gl.BindVertexArray(self.vertexArray)
	gl.DrawElements(gl.TRIANGLES, self.vertexCount, gl.UNSIGNED_INT, 0)
end


--===== builtin meshes =====--

function createBuiltins()
	cache["builtin.quad"] = {Mesh(
		{ 0, 0, 0,   0, 1, 0,   0, 0,
		  1, 0, 0,   0, 1, 0,   1, 0,
		  0, 1, 0,   0, 1, 0,   0, 1,
		  1, 1, 0,   0, 1, 0,   1, 1 },
		{ 0, 1, 3, 0, 3, 2 }
	)}
end


return module