summaryrefslogtreecommitdiff
path: root/model.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'model.cpp')
-rw-r--r--model.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/model.cpp b/model.cpp
new file mode 100644
index 0000000..7ae69f3
--- /dev/null
+++ b/model.cpp
@@ -0,0 +1,151 @@
+#include "maths.hpp"
+#include "model.hpp"
+
+extern "C" {
+#include "memory.h"
+#include "pack.h"
+#include "plat.h"
+}
+
+#include <string.h>
+
+void Model_Loader::init(Device* device, Asset_Arena* shader_arena) {
+ dev = device;
+ shaders = shader_arena;
+}
+
+Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) {
+ char magic[4];
+ int vbo_size, ibo_size, node_count, i, coff, icoff, vcoff;
+ uint8_t* verts;
+ uint16_t* indices;
+ Model* r;
+ Mesh* meshes;
+ void* vram;
+ Context* ctx;
+ Buffer_Id stage_verts, stage_indices;
+ pack_read(f, magic, 4);
+ if (
+ magic[0] != 'M' ||
+ magic[1] != 'O' ||
+ magic[2] != 'D' ||
+ magic[3] != 'L'
+ ) {
+ print_err("Invalid model.\n");
+ return 0;
+ }
+ pack_read(f, &vbo_size, 4);
+ pack_read(f, &ibo_size, 4);
+ pack_read(f, &node_count, 4);
+ verts = (uint8_t*)arena_alloc(s, vbo_size);
+ indices = (uint16_t*)arena_alloc(s, ibo_size);
+ r = (Model*)arena_alloc(a, sizeof *r + node_count * sizeof(Mesh));
+ r->mesh_count = node_count;
+ meshes = r->get_meshes();
+ for (i = 0, coff = 0, icoff = 0, vcoff = 0; i < node_count; i++) {
+ Mesh& mesh = meshes[i];
+ int vertex_size, vertex_count;
+ pack_read(f, magic, 4);
+ if (
+ magic[0] != 'M' ||
+ magic[1] != 'E' ||
+ magic[2] != 'S' ||
+ magic[3] != 'H'
+ ) {
+ print_err("Invalid mesh.\n");
+ return 0;
+ }
+ mesh.offset = icoff;
+ mesh.parent = 0;
+ mesh.shader = ((Shader*)shaders->load("surface.csh"))->id;
+ pack_read(f, &vertex_size, 4);
+ pack_read(f, &mesh.count, 4);
+ pack_read(f, &vertex_count, 4);
+ pack_read(f, &verts[coff], vertex_count * vertex_size);
+ pack_read(f, &indices[icoff], mesh.count * sizeof *indices);
+ mesh.vbo_offset = vcoff;
+ icoff += mesh.count;
+ coff += vertex_size * vertex_count;
+ vcoff += vertex_count;
+ }
+ stage_verts = dev->create_buffer(
+ vbo_size,
+ Buffer_Flags::copy_src |
+ Buffer_Flags::cpu_readwrite
+ );
+ stage_indices = dev->create_buffer(
+ ibo_size,
+ Buffer_Flags::copy_src |
+ Buffer_Flags::cpu_readwrite
+ );
+ vram = dev->map_buffer(stage_verts, 0, vbo_size);
+ memcpy(vram, verts, vbo_size);
+ dev->unmap_buffer(stage_verts);
+ vram = dev->map_buffer(stage_indices, 0, ibo_size);
+ memcpy(vram, indices, ibo_size);
+ dev->unmap_buffer(stage_indices);
+ r->vbo = dev->create_buffer(
+ vbo_size,
+ Buffer_Flags::copy_dst |
+ Buffer_Flags::vertex_buffer
+ );
+ r->ibo = dev->create_buffer(
+ ibo_size,
+ Buffer_Flags::copy_dst |
+ Buffer_Flags::index_buffer
+ );
+ ctx = &dev->acquire();
+ ctx->copy(r->vbo, stage_verts);
+ ctx->copy(r->ibo, stage_indices);
+ dev->submit(*ctx);
+ dev->destroy_buffer(stage_verts);
+ dev->destroy_buffer(stage_indices);
+ return r;
+}
+
+void Model_Loader::unload(Asset* a) {
+ Model* m = (Model*)a;
+ dev->destroy_buffer(m->vbo);
+ dev->destroy_buffer(m->ibo);
+}
+
+void Model::render(
+ Device* dev,
+ Arena* a,
+ Render_Pass& pass,
+ Buffer_Id config
+) {
+ int i, c = mesh_count;
+ Mesh* meshes = get_meshes();
+ Context& ctx = dev->get_ctx();
+ 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")
+ }, {}};
+ Index_Buffer_Binding ibb = {
+ .id = ibo,
+ .offset = 0
+ };
+ Draw draw{};
+ Pipeline_Builder pb(a);
+ draw.verts = vbb;
+ draw.inds = ibb;
+ draw.vertex_count = mesh.count;
+ draw.instance_count = 1;
+ draw.first_vertex = mesh.offset;
+ draw.vertex_offset = mesh.vbo_offset;
+ pb.begin(dev);
+ pb.shader(mesh.shader);
+ pb.cbuffer(
+ shader.descriptor_binding("config_buffer"),
+ config
+ );
+ pb.vertex_format(shader.vf);
+ Pipeline& pip = pb.build();
+ ctx.submit(draw, pip, pass);
+ }
+}