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 =====-- local function builtin(name, vertices, indices) local vao, vbo, ebo, count = createMesh(vertices, indices) cache[name] = { {vao=vao, vbo=vbo, ebo=ebo, count=count } } end init = function() builtin( "builtin.quad", { 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