summaryrefslogtreecommitdiff
path: root/honey/asset/mesh.lua
diff options
context:
space:
mode:
Diffstat (limited to 'honey/asset/mesh.lua')
-rw-r--r--honey/asset/mesh.lua150
1 files changed, 150 insertions, 0 deletions
diff --git a/honey/asset/mesh.lua b/honey/asset/mesh.lua
new file mode 100644
index 0000000..876c5e4
--- /dev/null
+++ b/honey/asset/mesh.lua
@@ -0,0 +1,150 @@
+local gl = honey.gl
+
+local module = {}
+setmetatable(module, {__index=_G})
+setfenv(1, module)
+
+
+-- append the 8 floats per vertex to the vertices table
+local function insertVertex(vertices, attrib, vertex)
+ local pos = 3*vertex.v_idx
+ for i=1,3 do
+ table.insert(vertices, attrib.vertices[pos+i])
+ end
+
+ local normal = 3*vertex.vn_idx
+ for i=1,3 do
+ table.insert(vertices, attrib.normals[normal+i])
+ end
+
+ local tex = 2*vertex.vt_idx
+ for i=1,2 do
+ table.insert(vertices, attrib.texcoords[tex+i])
+ end
+end
+
+
+-- creates a table of floats representing vertex data
+-- and a table of ints representing face indices within the vertices
+local 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
+
+
+-- public helper function (used in some other places, like trimesh construction)
+-- packages the vertices & indices tables from loadShape into a single array
+loadFile = function(filename)
+ local flags = honey.tinyobj.FLAG_TRIANGULATE
+ 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, {vertices=vertices, indices=indices})
+ end
+ return meshes
+end
+
+
+-- helper function to create a gl vertex array object from (vertices, indices) pair
+local function createMesh(vertices, indices)
+ vao = gl.GenVertexArrays()
+ vbo = gl.GenBuffers()
+ ebo = gl.GenBuffers()
+
+ gl.BindVertexArray(vao)
+ gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
+ gl.BufferData(gl.ARRAY_BUFFER, gl.FLOAT, vertices, gl.STATIC_DRAW)
+
+ gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo)
+ gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.UNSIGNED_INT, indices, gl.STATIC_DRAW)
+
+ local stride = 8
+ local offset = 0
+
+ -- position
+ gl.VertexAttribPointer(0, 3, false, stride, offset)
+ gl.EnableVertexAttribArray(0)
+ offset = offset+3
+
+ -- normal
+ gl.VertexAttribPointer(1, 3, false, stride, offset)
+ gl.EnableVertexAttribArray(1)
+ offset = offset+3
+
+ -- texture
+ gl.VertexAttribPointer(2, 2, false, stride, offset)
+ gl.EnableVertexAttribArray(2)
+ offset = offset+2
+
+ return vao, vbo, ebo, #vertices
+end
+
+
+local cache = {}
+
+
+-- get a gl vertex array object + vertex count
+get = function(filename, index)
+ if not cache[filename] then
+ local c = {}
+ local meshes = loadFile(filename)
+ for _, m in ipairs(meshes) do
+ local vao, vbo, ebo, count = createMesh(m.vertices, m.indices)
+ table.insert(c, { vao=vao, vbo=vbo, ebo=ebo, count=count })
+ end
+ cache[filename] = c
+ end
+ local m = cache[filename][index]
+ return m.vao, m.count
+end
+
+
+-- forget a mesh
+forget = function(filename)
+ if not cache[filename] then return end
+ for _, m in ipairs(cache[filename]) do
+ gl.DeleteBuffers(m.vbo)
+ gl.DeleteBuffers(m.ebo)
+ gl.DeleteVertexArrays(m.vao)
+ end
+ cache[filename] = nil
+end
+
+
+-- clear the cache
+clearCache = function()
+ for key in pairs(cache) do
+ forget(key)
+ end
+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