summaryrefslogtreecommitdiff
path: root/model.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-29 13:40:55 +1100
committerquou <quou@disroot.org>2024-12-29 13:41:56 +1100
commit928eba3845d6017d133048cf04c1f816d87941b0 (patch)
tree50f8c52b6f6eb0adbde2666c50ff10dd3920616a /model.cpp
parent7383cfcbe8ade4dce057608e971e8cb7d4b1feb7 (diff)
model hierarchy support
Diffstat (limited to 'model.cpp')
-rw-r--r--model.cpp66
1 files changed, 60 insertions, 6 deletions
diff --git a/model.cpp b/model.cpp
index 4c3e40f..e8be727 100644
--- a/model.cpp
+++ b/model.cpp
@@ -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();