diff options
Diffstat (limited to 'model.cpp')
-rw-r--r-- | model.cpp | 66 |
1 files changed, 60 insertions, 6 deletions
@@ -9,6 +9,11 @@ extern "C" { #include <string.h> +struct MVP_Cbuffer { + m4f model; + m4f view_projection; +}; + void Model_Loader::init(Device* device, Asset_Arena* shader_arena) { dev = device; shaders = shader_arena; @@ -55,6 +60,8 @@ Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) { for (i = 0, coff = 0, icoff = 0, vcoff = 0; i < node_count; i++) { Mesh& mesh = meshes[i]; int vertex_size, vertex_count; + char shader_name[28]; + Shader* shader; pack_read(f, magic, 4); if ( magic[0] != 'M' || @@ -65,12 +72,20 @@ Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) { print_err("Invalid mesh.\n"); return 0; } + pack_read(f, shader_name, sizeof shader_name); mesh.offset = icoff; - mesh.parent = 0; - mesh.shader = ((Shader*)shaders->load("surface.csh"))->id; + shader = (Shader*)shaders->load(shader_name); + assert(shader != 0); + mesh.shader = shader->id; + mesh.mvp_binding = shader->descriptor_binding("c_mvp"); + mesh.mesh_binding = shader->binding_index("mesh"); + assert(mesh.mvp_binding >= 0); + assert(mesh.mesh_binding >= 0); pack_read(f, &vertex_size, 4); pack_read(f, &mesh.count, 4); pack_read(f, &vertex_count, 4); + pack_read(f, &mesh.parent, 4); + pack_read(f, &mesh.local, 64); pack_read(f, &verts[coff], vertex_count * vertex_size); pack_read(f, &indices[icoff], mesh.count * sizeof *indices); mesh.vbo_offset = vcoff; @@ -90,6 +105,11 @@ Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) { Buffer_Flags::copy_dst | Buffer_Flags::index_buffer ); + r->mvp = dev->create_buffer( + sizeof(MVP_Cbuffer) * node_count, + Buffer_Flags::constant_buffer | + Buffer_Flags::cpu_readwrite + ); ctx = &dev->acquire(); ctx->copy(r->vbo, stage_verts); ctx->copy(r->ibo, stage_indices); @@ -103,24 +123,56 @@ void Model_Loader::unload(Asset* a) { Model* m = (Model*)a; dev->destroy_buffer(m->vbo); dev->destroy_buffer(m->ibo); + dev->destroy_buffer(m->mvp); +} + +const m4f& Mesh::get_world(Model& m) { + if (world_dirty) { + if (parent) + world = m.get_meshes()[parent].get_world(m) * local; + else + world = local; + world_dirty = false; + } + return world; +} + +void Model::update_transforms() { + int i, c = mesh_count; + Mesh* meshes = get_meshes(); + for (i = 0; i < c; i++) + meshes[i].world_dirty = true; + for (i = 0; i < c; i++) + meshes[i].get_world(*this); } void Model::render( Device* dev, Arena* a, Render_Pass& pass, - Buffer_Id config + const m4f& transform, + const m4f& view_projection ) { int i, c = mesh_count; Mesh* meshes = get_meshes(); Context& ctx = dev->get_ctx(); + MVP_Cbuffer* cbuffers = (MVP_Cbuffer*)dev->map_buffer( + mvp, + 0, + c * sizeof *cbuffers + ); + for (i = 0; i < c; i++) { + cbuffers[i].view_projection = view_projection; + cbuffers[i].model = transform * meshes[i].world; + } + dev->unmap_buffer(mvp); for (i = 0; i < c; i++) { Mesh& mesh = meshes[i]; Shader& shader = dev->get_shader(mesh.shader); Vertex_Buffer_Binding vbb[] = {{ .id = vbo, .offset = 0, - .target = shader.binding_index("mesh") + .target = mesh.mesh_binding }, {}}; Index_Buffer_Binding ibb = { .id = ibo, @@ -138,8 +190,10 @@ void Model::render( pb.depth(true, true, Depth_Mode::less); pb.shader(mesh.shader); pb.cbuffer( - shader.descriptor_binding("config_buffer"), - config + mesh.mvp_binding, + mvp, + i * sizeof(MVP_Cbuffer), + sizeof(MVP_Cbuffer) ); pb.vertex_format(shader.vf); Pipeline& pip = pb.build(); |