diff options
Diffstat (limited to 'model.cpp')
-rw-r--r-- | model.cpp | 240 |
1 files changed, 162 insertions, 78 deletions
@@ -150,24 +150,13 @@ Asset* Model_Loader::load( Buffer_Flags::copy_dst | Buffer_Flags::index_buffer ); - r->mvp = dev->create_buffer( - filename, - sizeof(MVP_Cbuffer) * node_count, - Buffer_Flags::constant_buffer | - Buffer_Flags::cpu_readwrite - ); - r->mat = dev->create_buffer( - filename, - sizeof(Mat_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); dev->submit(*ctx); dev->destroy_bufferi(stage_verts); dev->destroy_bufferi(stage_indices); + r->update_transforms(); return r; } @@ -175,8 +164,6 @@ 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); - dev->destroy_buffer(m->mat); } const m4f& Mesh::get_world(Model& m) { @@ -199,28 +186,124 @@ void Model::update_transforms() { meshes[i].get_world(*this); } -void Model::update_cbuffers( +void Material_Loader::init( + Asset_Arena* texture_arena, + Texture_Id dt +) { + default_tex = dt; + textures = texture_arena; +} + +Asset* Material_Loader::load( + Arena* a, + Arena* s, + const char* filename, + Pack_File* f +) { + Material_File mf; + Material* m = (Material*)arena_alloc(a, sizeof *m); + auto read_name = [&](int len) { + char* r = (char*)arena_alloc(s, len + 1); + r[pack_read(f, r, len)] = 0; + return r; + }; + auto read_tex = [&](int len) { + if (!len) return default_tex; + const char* name = read_name(len); + auto t = (Texture*)textures->load(name); + if (!t) + return default_tex; + return t->id; + }; + (void)filename; + pack_read(f, &mf, sizeof mf); + if ( + mf.magic[0] != 'M' || + mf.magic[1] != 'T' || + mf.magic[2] != 'R' || + mf.magic[3] != 'L' + ) return 0; + m->metalness = mf.metalness; + m->roughness = mf.roughness; + m->ao = mf.ao; + m->albedo = v3f( + (float)((mf.albedo >> 16) & 0xff) / 255.0f, + (float)((mf.albedo >> 8) & 0xff) / 255.0f, + (float)((mf.albedo) & 0xff) / 255.0f + ); + m->tex.albedo = read_tex(mf.albedo_tex_len); + m->tex.ao = read_tex(mf.ao_tex_len); + m->tex.metal = read_tex(mf.metal_tex_len); + m->tex.rough = read_tex(mf.rough_tex_len); + m->tex.normal = read_tex(mf.normal_tex_len); + return m; +} + +void Material_Loader::unload(Asset* a) { + (void)a; +} + +void Camera::init(float vfov, const v3f& f, const v3f& p) { + fov = vfov; + forward = f; + position = p; + near = 0.1f; + far = 1000.0f; + asp = 1.0f; +} + +m4f Camera::get_view() const { + v3f up(0.0f, 1.0f, 0.0f); + return m4f::lookat(position, position + forward, up); +} + +m4f Camera::get_proj() const { + return m4f::pers(fov, asp, near, far); +} + +void Model_Instance::init(Device* dev, Model* model) { + m = model; + mvp = dev->create_buffer( + "Model instance MVP", + sizeof(MVP_Cbuffer) * m->mesh_count, + Buffer_Flags::constant_buffer | + Buffer_Flags::cpu_readwrite + ); + mat = dev->create_buffer( + "Model instance material", + sizeof(Mat_Cbuffer) * m->mesh_count, + Buffer_Flags::constant_buffer | + Buffer_Flags::cpu_readwrite + ); +} + +void Model_Instance::destroy(Device* dev) { + dev->destroy_buffer(mat); + dev->destroy_buffer(mvp); +} + +void Model_Instance::update_cbuffers( Device* dev, - const m4f& transform, - const m4f& view_projection + const Camera& cam ) { - int i, c = mesh_count; - Mesh* meshes = get_meshes(); - MVP_Cbuffer* cbuffers = (MVP_Cbuffer*)dev->map_buffer( + int i, c = m->mesh_count; + Mesh* meshes = m->get_meshes(); + MVP_Cbuffer* mvps = (MVP_Cbuffer*)dev->map_buffer( mvp, 0, - c * sizeof *cbuffers + c * sizeof *mvps ); Mat_Cbuffer* mats = (Mat_Cbuffer*)dev->map_buffer( mat, 0, - c * sizeof *cbuffers + c * sizeof *mats ); + m4f view_projection = cam.get_proj(); for (i = 0; i < c; i++) { Mat_Cbuffer& mat = mats[i]; Material& sm = *meshes[i].material; - cbuffers[i].view_projection = view_projection; - cbuffers[i].model = transform * meshes[i].world; + mvps[i].view_projection = view_projection; + mvps[i].model = transform * meshes[i].world; mat.albedo[0] = sm.albedo.x; mat.albedo[1] = sm.albedo.y; mat.albedo[2] = sm.albedo.z; @@ -232,26 +315,26 @@ void Model::update_cbuffers( dev->unmap_buffer(mat); } -void Model::render( +void Model_Instance::render( Device* dev, Arena* a, Render_Pass& pass, Sampler_Id sampler ) { - int i, c = mesh_count; - Mesh* meshes = get_meshes(); + int i, c = m->mesh_count; + Mesh* meshes = m->get_meshes(); Context& ctx = dev->get_ctx(); bool depth_only = !pass.colour_count; for (i = 0; i < c; i++) { Mesh& mesh = meshes[i]; Shader& shader = dev->get_shader(mesh.shader); Vertex_Buffer_Binding vbb[] = {{ - .id = vbo, + .id = m->vbo, .offset = 0, .target = mesh.mesh_binding }, {}}; Index_Buffer_Binding ibb = { - .id = ibo, + .id = m->ibo, .offset = 0 }; Draw draw{}; @@ -288,59 +371,60 @@ void Model::render( } } -void Material_Loader::init( - Asset_Arena* texture_arena, - Texture_Id dt +void Model_Scene::init( + Arena* arena, + int max_instances, + Sampler_Id s ) { - default_tex = dt; - textures = texture_arena; + instances = (Model_Instance*)arena_alloc(arena, max_instances); + count = 0; + max = max_instances; + sampler = s; } -Asset* Material_Loader::load( - Arena* a, - Arena* s, - const char* filename, - Pack_File* f +Model_Instance* Model_Scene::instantiate( + Device* dev, + Model* model ) { - Material_File mf; - Material* m = (Material*)arena_alloc(a, sizeof *m); - auto read_name = [&](int len) { - char* r = (char*)arena_alloc(s, len + 1); - r[pack_read(f, r, len)] = 0; - return r; - }; - auto read_tex = [&](int len) { - if (!len) return default_tex; - const char* name = read_name(len); - auto t = (Texture*)textures->load(name); - if (!t) - return default_tex; - return t->id; - }; - (void)filename; - pack_read(f, &mf, sizeof mf); - if ( - mf.magic[0] != 'M' || - mf.magic[1] != 'T' || - mf.magic[2] != 'R' || - mf.magic[3] != 'L' - ) return 0; - m->metalness = mf.metalness; - m->roughness = mf.roughness; - m->ao = mf.ao; - m->albedo = v3f( - (float)((mf.albedo >> 16) & 0xff) / 255.0f, - (float)((mf.albedo >> 8) & 0xff) / 255.0f, - (float)((mf.albedo) & 0xff) / 255.0f - ); - m->tex.albedo = read_tex(mf.albedo_tex_len); - m->tex.ao = read_tex(mf.ao_tex_len); - m->tex.metal = read_tex(mf.metal_tex_len); - m->tex.rough = read_tex(mf.rough_tex_len); - m->tex.normal = read_tex(mf.normal_tex_len); - return m; + Model_Instance* instance = &instances[count++]; + assert(count <= max); + instance->init(dev, model); + return instance; } -void Material_Loader::unload(Asset* a) { - (void)a; +void Model_Scene::uninstantiate( + Device* dev, + Model_Instance* model +) { + int idx = model - instances; + int last = count - 1; + model->destroy(dev); + instances[idx] = instances[last]; + count = last; +} + +void Model_Scene::update(const Camera& cam, Device* dev) { + int i; + Model_Instance* instance = instances; + for (i = 0; i < count; i++, instance++) + instance->update_cbuffers(dev, cam); +} + +void Model_Scene::render( + Device* dev, + Arena* a, + Render_Pass& pass, + Sampler_Id sampler +) { + int i; + Model_Instance* instance = instances; + for (i = 0; i < count; i++, instance++) + instance->render(dev, a, pass, sampler); +} + +void Model_Scene::destroy(Device* dev) { + int i; + Model_Instance* instance = instances; + for (i = 0; i < count; i++, instance++) + instance->destroy(dev); } |