From 014077c89bb3c50718d56430f387109ad43508b6 Mon Sep 17 00:00:00 2001 From: quou Date: Mon, 13 Jan 2025 20:56:13 +1100 Subject: basic picking and debug rendering --- model.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 7 deletions(-) (limited to 'model.cpp') diff --git a/model.cpp b/model.cpp index 9e78b19..03a24e0 100644 --- a/model.cpp +++ b/model.cpp @@ -9,6 +9,8 @@ extern "C" { } #include +#include +#include struct MVP_Cbuffer { m4f model; @@ -273,7 +275,7 @@ m4f Camera::get_proj() const { return m4f::pers(fov, asp, near, far); } -void Model_Instance::init(Device* dev, Model* model) { +void Model_Instance::init(Device* dev, Heap* h, Model* model) { m = model; mvp = dev->create_buffer( "Model instance MVP", @@ -287,11 +289,26 @@ void Model_Instance::init(Device* dev, Model* model) { Buffer_Flags::constant_buffer | Buffer_Flags::cpu_readwrite ); + bounds = (AABB*)heap_alloc( + h, + sizeof *bounds * model->mesh_count + ); } -void Model_Instance::destroy(Device* dev) { +void Model_Instance::destroy(Device* dev, Heap* h) { dev->destroy_buffer(mat); dev->destroy_buffer(mvp); + heap_free(h, bounds); +} + +void Model_Instance::update() { + Mesh* meshes = m->get_meshes(); + int i, c = m->mesh_count; + for (i = 0; i < c; i++) + bounds[i] = m4f::transform( + transform * meshes[i].world, + meshes[i].bound + ); } void Model_Instance::update_cbuffers( @@ -400,12 +417,34 @@ void Model_Instance::render( } } +int Model_Instance::pick(const v3f& o, const v3f& d) { + int i, c = m->mesh_count; + for (i = 0; i < c; i++) { + AABB& b = bounds[i]; + v3f id = 1.0f / d; + v3f t1 = (b.min - o) * id; + v3f t2 = (b.max - o) * id; + float tmin = std::max(std::max(std::min(t1.x, t2.x), std::min(t1.y, t2.y)), std::min(t1.z, t2.z)); + float tmax = std::min(std::min(std::max(t1.x, t2.x), std::max(t1.y, t2.y)), std::max(t1.z, t2.z)); + if (tmax < 0.0f || tmin > tmax) + { + continue; + } + return i; + } + return -1; +} + void Model_Scene::init( Arena* arena, int max_instances, Sampler_Id s ) { - instances = (Model_Instance*)arena_alloc(arena, max_instances); + int hs; + h = (Heap*)arena_alloc(arena, sizeof *h); + hs = arena->size - arena->ptr - allocation_default_alignment - 1; + init_heap(h, arena_alloc(arena, hs), hs); + instances = (Model_Instance*)heap_alloc(h, max_instances); count = 0; max = max_instances; sampler = s; @@ -417,7 +456,7 @@ Model_Instance* Model_Scene::instantiate( ) { Model_Instance* instance = &instances[count++]; assert(count <= max); - instance->init(dev, model); + instance->init(dev, h, model); return instance; } @@ -427,7 +466,7 @@ void Model_Scene::uninstantiate( ) { int idx = model - instances; int last = count - 1; - model->destroy(dev); + model->destroy(dev, h); instances[idx] = instances[last]; count = last; } @@ -435,8 +474,10 @@ void Model_Scene::uninstantiate( void Model_Scene::update(const Camera& cam, Device* dev) { int i; Model_Instance* instance = instances; - for (i = 0; i < count; i++, instance++) + for (i = 0; i < count; i++, instance++) { + instance->update(); instance->update_cbuffers(dev, cam); + } } void Model_Scene::render( @@ -456,5 +497,28 @@ void Model_Scene::destroy(Device* dev) { int i; Model_Instance* instance = instances; for (i = 0; i < count; i++, instance++) - instance->destroy(dev); + instance->destroy(dev, h); +} + +std::pair Model_Scene::pick( + const Camera& cam, + int w, + int h, + int mx, + int my +) { + int i, c = count; + v2f uv = (2.0f * v2f(mx, my) - v2f(w, h)) / (float)h; + v4f e = + cam.get_proj().inverse() * + v4f(uv.x, uv.y, -1.0f, 1.0f); + e.z = -1.0f; e.w = 0.0f; + v4f d4 = cam.get_view().inverse() * e; + v3f d = v3f::normalised(v3f(d4.x, d4.y, d4.z)); + for (i = 0; i < c; i++) { + int m = instances[i].pick(cam.position, d); + if (m >= 0) return { &instances[i], m }; + } + return { 0, -1 }; } + -- cgit v1.2.3-54-g00ecf