diff --git a/examples/render_groups/main.cpp b/examples/render_groups/main.cpp index 39365d8..25320c9 100644 --- a/examples/render_groups/main.cpp +++ b/examples/render_groups/main.cpp @@ -177,7 +177,7 @@ main() renDoRenderLoop(rs, 60, doFrameCallbackPre); #endif - model* ret = assetLoadFromFile(rs->models, + model* ret = assetLoadFromFile(rs->assets, rs->arena, "../data/blender/spaceship.gltf"); assert(ret != nullptr); diff --git a/include/asset.h b/include/asset.h index 27af3b2..6880d2b 100644 --- a/include/asset.h +++ b/include/asset.h @@ -1,6 +1,7 @@ #pragma once +#include #include #include "animation.h" @@ -13,6 +14,8 @@ struct mesh { + GLenum draw_mode; // NOTE: GL_LINES, GL_TRIANGLES + GLenum usage; // NOTE: GL_STATIC_DRAW, GL_DYNAMIC_DRAW uint num_vertices; uint num_indices; glm::vec3* vertices; @@ -21,8 +24,8 @@ struct mesh // FIXME: will have to use vec2 here to be able to use memcpy // this will break render_object::initGLFLoatBuffer logic which expects // vec3 - glm::vec3* texture_coords; - glm::mat4 xform; + glm::vec2* texture_coords; + glm::mat4* xform; }; #define MAX_PATH_SIZE 256 diff --git a/include/renderer.h b/include/renderer.h index 7200f93..2e99707 100644 --- a/include/renderer.h +++ b/include/renderer.h @@ -56,7 +56,7 @@ struct render_state uint render_group_count; // WIP - model_assets* models; + model_assets* assets; memory_arena* arena; // FIXME: should be a hashmap for textures loaded from assets // ie) pallete textures diff --git a/src/asset.cpp b/src/asset.cpp index cd0536a..2aa72b0 100644 --- a/src/asset.cpp +++ b/src/asset.cpp @@ -21,9 +21,9 @@ const char* getElementType(int type) { switch (type) { - case 2: return "VEC2"; - case 3: return "VEC3"; - case 4: return "VEC4"; + case 2: return "TINYGLTF_TYPE_VEC2"; + case 3: return "TINYGLTF_TYPE_VEC3"; + case 4: return "TINYGLTF_TYPE_VEC4"; case 65: return "TINYGLTF_TYPE_SCALAR"; default: return "UNKNOWN"; } @@ -118,6 +118,7 @@ dumpNodes(tinygltf::Model t_mdl) { for (tinygltf::Node node : t_mdl.nodes) { LOG(Debug) << "##################\n"; + LOG(Debug) << "node name: " << node.name << "\n"; LOG(Debug) << "node mesh idx: " << node.mesh << "\n"; if (node.mesh >= 0) { @@ -141,6 +142,70 @@ dumpNodes(tinygltf::Model t_mdl) } } +bool +copyBuffer(uint8_t*& buffer_ref, + memory_arena* arena, + int acc_idx, + const tinygltf::Model& t_mdl) +{ + const tinygltf::Accessor& acc = t_mdl.accessors[acc_idx]; + const tinygltf::BufferView& bv = t_mdl.bufferViews[acc.bufferView]; + const tinygltf::Buffer& t_buf = t_mdl.buffers[bv.buffer]; + + if (bv.target == TINYGLTF_TARGET_ARRAY_BUFFER) { + assert(acc.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT + && (acc.type == TINYGLTF_TYPE_VEC3 + || acc.type == TINYGLTF_TYPE_VEC2)); + } else if (bv.target == TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER) { + assert(acc.type == TINYGLTF_TYPE_SCALAR + && acc.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT); + } else { + LOG(Error) << "unknown target\n"; + return false; + } + + assert(bv.byteStride == 0); + buffer_ref = (uint8_t*) arenaAllocateBlock(arena, bv.byteLength); + std::memcpy(buffer_ref, &t_buf.data[bv.byteOffset], bv.byteLength); + + return buffer_ref == nullptr; +} + +bool +parseMeshNode(mesh& m, + memory_arena* arena, + const tinygltf::Node& node, + const tinygltf::Model& t_mdl) +{ + tinygltf::Mesh t_mesh = t_mdl.meshes[node.mesh]; + // NOTE: assume only 1 primitive object per mesh + assert(t_mdl.meshes[node.mesh].primitives.size() == 1); + tinygltf::Primitive prim = t_mesh.primitives[0]; + + // NOTE: verify assumptions about input + assert(prim.attributes.find("POSITION") != prim.attributes.end() + && prim.attributes.find("NORMAL") != prim.attributes.end() + && prim.attributes.find("TEXCOORD_0") != prim.attributes.end() + && prim.indices >= 0); + + const tinygltf::Accessor& vert_acc = + t_mdl.accessors[prim.attributes["POSITION"]]; + const tinygltf::Accessor& index_acc = t_mdl.accessors[prim.indices]; + m.num_vertices = vert_acc.count; + m.num_indices = index_acc.count; + m.draw_mode = prim.mode; + m.usage = GL_STATIC_DRAW; // TODO: logic for updating meshes + m.xform = (glm::mat4*) arenaAllocateBlock(arena, sizeof(glm::mat4)); + copyBuffer( + (uint8_t*&) m.vertices, arena, prim.attributes["POSITION"], t_mdl); + copyBuffer((uint8_t*&) m.normals, arena, prim.attributes["NORMAL"], t_mdl); + copyBuffer((uint8_t*&) m.texture_coords, + arena, prim.attributes["TEXCOORD_0"], t_mdl); + copyBuffer((uint8_t*&) m.indices, arena, prim.indices, t_mdl); + + return true; +} + model* assetLoadFromFile(model_assets* assets, memory_arena* arena, @@ -157,11 +222,25 @@ assetLoadFromFile(model_assets* assets, return nullptr; } + // NOTE: assume we're working with a single buffer + assert(t_mdl.buffers.size() == 1); model* mdl = initModel(assets, arena, t_mdl, filename); // TODO: also need to get each node xform // TODO: also need to dump textures/materials dumpNodes(t_mdl); + uint mesh_idx = 0; + + for (tinygltf::Node node : t_mdl.nodes) { + if (node.mesh >= 0) { + if (!parseMeshNode(mdl->meshes[mesh_idx++], arena, node, t_mdl)) { + // FIXME: error handling + LOG(Error) << "Some mesh parsing error\n"; + return nullptr; + } + } + } + return mdl; } diff --git a/src/render_object.cpp b/src/render_object.cpp index 7a216dc..b782ed9 100644 --- a/src/render_object.cpp +++ b/src/render_object.cpp @@ -297,6 +297,7 @@ loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in) initGLFloatBuffer(mi_in->normals, mi_in->num_vertices, ro_out->normal_buffer_id) && + // FIXME: this is broken now with tinygltf, need to use vec2 initGLFloatBuffer(mi_in->texture_coords, mi_in->num_vertices, ro_out->uv_buffer_id) && diff --git a/src/renderer.cpp b/src/renderer.cpp index fd4917e..0039a35 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -47,7 +47,7 @@ renInit(const char* title, render_state* rs = UTIL_ALLOC(1, render_state); rs->handles = UTIL_ALLOC(1, SDL_Handles); rs->arena = arenaInit(arena_size); - rs->models = assetInitBlock(rs->arena, asset_size); + rs->assets = assetInitBlock(rs->arena, asset_size); setDefaults(rs, viewport_dims); if (initSDL(rs->handles, SDL_init_flags) &&