From 6d9d393ae60bfc6b2625a5540cd60ffed478aa13 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 12 Mar 2026 01:15:26 +0000 Subject: Shared VAO for all 3 parts of RailVehicleClass Rearranges its LocationVertex to be 3 repeated Parts. Adds helpers to glvglVertexArray for useBuffer with various offsets. Render is then an iteration of the meshes and the location data at the nth offset. --- game/vehicles/railVehicle.cpp | 12 ++++----- game/vehicles/railVehicleClass.cpp | 50 ++++++++++++++++++++------------------ game/vehicles/railVehicleClass.h | 10 +++++--- gfx/gl/glVertexArray.h | 24 ++++++++++++++++-- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/game/vehicles/railVehicle.cpp b/game/vehicles/railVehicle.cpp index 4a0a22d..61f6c93 100644 --- a/game/vehicles/railVehicle.cpp +++ b/game/vehicles/railVehicle.cpp @@ -14,18 +14,18 @@ RailVehicle::RailVehicle(RailVehicleClassPtr rvc) : RailVehicleClass::Instance {rvc->instances.acquire()}, rvClass {std::move(rvc)}, location {[this](const BufferedLocation * l) { - this->get()->body = l->getRotationTransform(); - this->get()->bodyPos = l->position(); + this->get()->body.rotation = l->getRotationTransform(); + this->get()->body.position = l->position(); }}, bogies {{ {[this](const BufferedLocation * l) { - this->get()->front = l->getRotationTransform(); - this->get()->frontPos = l->position(); + this->get()->front.rotation = l->getRotationTransform(); + this->get()->front.position = l->position(); }, GlobalPosition3D {0, rvClass->wheelBase / 2.F, 0}}, {[this](const BufferedLocation * l) { - this->get()->back = l->getRotationTransform(); - this->get()->backPos = l->position(); + this->get()->back.rotation = l->getRotationTransform(); + this->get()->back.position = l->position(); }, GlobalPosition3D {0, -rvClass->wheelBase / 2.F, 0}}, }} diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp index d94d4ca..176fe82 100644 --- a/game/vehicles/railVehicleClass.cpp +++ b/game/vehicles/railVehicleClass.cpp @@ -7,6 +7,7 @@ #include #include #include +#include bool RailVehicleClass::persist(Persistence::PersistenceStore & store) @@ -20,12 +21,11 @@ std::any RailVehicleClass::createAt(const Location & position) const { return std::make_shared::InstanceProxy>(instances.acquire(LocationVertex { - .body = position.getRotationTransform(), - .front = position.getRotationTransform(), - .back = position.getRotationTransform(), - .bodyPos = position.pos, - .frontPos = {sincos(position.rot.x) * wheelBase * 0.5F, position.pos.z}, - .backPos = {sincos(position.rot.x) * wheelBase * -0.5F, position.pos.z}, + .body = {.rotation = position.getRotationTransform(), .position = position.pos}, + .front = {.rotation = position.getRotationTransform(), + .position = {sincos(position.rot.x) * wheelBase * 0.5F, position.pos.z}}, + .back = {.rotation = position.getRotationTransform(), + .position = {sincos(position.rot.x) * wheelBase * -0.5F, position.pos.z}}, })); } @@ -35,42 +35,44 @@ RailVehicleClass::postLoad() texture = getTexture(); glDebugScope _ {0}; bodyMesh->configureVAO(instanceVAO, 0) - .addAttribs(1); - bogies.front() - ->configureVAO(instancesBogiesVAO.front(), 0) - .addAttribs(1); - bogies.back() - ->configureVAO(instancesBogiesVAO.back(), 0) - .addAttribs(1); + .addAttribs(1); static_assert(sizeof(LocationVertex) == 144UL); } +void +RailVehicleClass::renderAllParts(const size_t count) const +{ + using PartPair = std::pair; + const auto bufferName = instances.bufferName(); + for (const auto & [mesh, part] : { + PartPair {bodyMesh, &LocationVertex::body}, + PartPair {bogies.front(), &LocationVertex::front}, + PartPair {bogies.back(), &LocationVertex::back}, + }) { + instanceVAO.useBuffer(1, bufferName, part); + mesh->drawInstanced(instanceVAO, static_cast(count)); + } +} + void RailVehicleClass::render(const SceneShader & shader, const Frustum &) const { - if (const auto count = static_cast(instances.size())) { + if (const auto count = (instances.size())) { glDebugScope _ {instanceVAO}; if (texture) { texture->bind(0); } shader.basicInst.use(); - instanceVAO.useBuffer(1, instances); - instancesBogiesVAO.front().useBuffer(1, instances); - instancesBogiesVAO.back().useBuffer(1, instances); - bodyMesh->drawInstanced(instanceVAO, count); - bogies.front()->drawInstanced(instancesBogiesVAO.front(), count); - bogies.back()->drawInstanced(instancesBogiesVAO.back(), count); + renderAllParts(count); } } void RailVehicleClass::shadows(const ShadowMapper & mapper, const Frustum &) const { - if (const auto count = static_cast(instances.size())) { + if (const auto count = instances.size()) { glDebugScope _ {instanceVAO}; mapper.dynamicPointInst.use(); - bodyMesh->drawInstanced(instanceVAO, count); - bogies.front()->drawInstanced(instancesBogiesVAO.front(), count); - bogies.back()->drawInstanced(instancesBogiesVAO.back(), count); + renderAllParts(count); } } diff --git a/game/vehicles/railVehicleClass.h b/game/vehicles/railVehicleClass.h index ccff3e2..fe27230 100644 --- a/game/vehicles/railVehicleClass.h +++ b/game/vehicles/railVehicleClass.h @@ -20,8 +20,12 @@ public: [[nodiscard]] std::any createAt(const Location &) const override; struct LocationVertex { - glm::mat3 body, front, back; - GlobalPosition3D bodyPos, frontPos, backPos; + struct Part { + glm::mat3 rotation; + GlobalPosition3D position; + }; + + Part body, front, back; }; std::array bogies; @@ -38,10 +42,10 @@ protected: friend Persistence::SelectionPtrBase>; bool persist(Persistence::PersistenceStore & store) override; void postLoad() override; + void renderAllParts(size_t count) const; private: glVertexArray instanceVAO; - std::array instancesBogiesVAO; }; using RailVehicleClassPtr = std::shared_ptr; diff --git a/gfx/gl/glVertexArray.h b/gfx/gl/glVertexArray.h index 6630b70..791f74f 100644 --- a/gfx/gl/glVertexArray.h +++ b/gfx/gl/glVertexArray.h @@ -125,13 +125,33 @@ namespace Impl { template void - useBuffer(GLuint binding, const glAllocated & buffer) const + useBuffer(GLuint binding, const glAllocated & buffer, GLsizei offset = 0) const requires requires { { buffer.bufferName() } -> std::same_as; } { using T = typename glAllocated::value_type; - glVertexArrayVertexBuffer(name, binding, buffer.bufferName(), 0, sizeof(T)); + useBuffer(binding, buffer.bufferName(), sizeof(T), offset); + } + + template + void + useBuffer(GLuint binding, GLuint bufferName, auto V::* mbr) const + { + useBuffer(binding, bufferName, sizeof(V), VertexArrayConfigurator::MP {mbr}); + } + + template + void + useBuffer(GLuint binding, GLuint bufferName, GLintptr offset = 0) const + { + useBuffer(binding, bufferName, sizeof(V), offset); + } + + void + useBuffer(GLuint binding, GLuint bufferName, GLsizei stride, GLintptr offset = 0) const + { + glVertexArrayVertexBuffer(name, binding, bufferName, offset, stride); } }; } -- cgit v1.3