diff options
Diffstat (limited to 'game/vehicles')
| -rw-r--r-- | game/vehicles/linkHistory.cpp | 18 | ||||
| -rw-r--r-- | game/vehicles/railVehicle.cpp | 59 | ||||
| -rw-r--r-- | game/vehicles/railVehicle.h | 10 | ||||
| -rw-r--r-- | game/vehicles/railVehicleClass.cpp | 59 | ||||
| -rw-r--r-- | game/vehicles/railVehicleClass.h | 23 | ||||
| -rw-r--r-- | game/vehicles/train.cpp | 16 | ||||
| -rw-r--r-- | game/vehicles/train.h | 11 | ||||
| -rw-r--r-- | game/vehicles/vehicle.cpp | 2 | ||||
| -rw-r--r-- | game/vehicles/vehicle.h | 4 |
9 files changed, 115 insertions, 87 deletions
diff --git a/game/vehicles/linkHistory.cpp b/game/vehicles/linkHistory.cpp index e6bab36..77840ed 100644 --- a/game/vehicles/linkHistory.cpp +++ b/game/vehicles/linkHistory.cpp @@ -1,17 +1,27 @@ #include "linkHistory.h" #include "game/network/link.h" #include <memory> +#include <optional> LinkHistory::Entry LinkHistory::add(const Link::WPtr & l, unsigned char d) { + constexpr auto HISTORY_KEEP_LENGTH = 500'000.F; + while (const auto newLength = [this]() -> std::optional<decltype(totalLen)> { + if (!links.empty()) { + const auto newLength = totalLen - links.back().first.lock()->length; + if (newLength >= HISTORY_KEEP_LENGTH) { + return newLength; + } + } + return std::nullopt; + }()) { + totalLen = newLength.value(); + links.pop_back(); + } links.insert(links.begin(), {l, d}); const auto lp = l.lock(); totalLen += lp->length; - while (totalLen >= 1000000.F && !links.empty()) { - totalLen -= links.back().first.lock()->length; - links.pop_back(); - } return {lp, d}; } diff --git a/game/vehicles/railVehicle.cpp b/game/vehicles/railVehicle.cpp index 59d1e83..b5de833 100644 --- a/game/vehicles/railVehicle.cpp +++ b/game/vehicles/railVehicle.cpp @@ -11,48 +11,46 @@ #include <maths.h> #include <ray.h> -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(); - }}, - bogies {{ - {[this](const BufferedLocation * l) { - this->get()->front = l->getRotationTransform(); - this->get()->frontPos = l->position(); - }, - GlobalPosition3D {0, rvClass->wheelBase / 2.F, 0}}, - {[this](const BufferedLocation * l) { - this->get()->back = l->getRotationTransform(); - this->get()->backPos = l->position(); - }, - GlobalPosition3D {0, -rvClass->wheelBase / 2.F, 0}}, - }} +RailVehicle::RailVehicle(RailVehicleClassPtr rvc, GlobalPosition3D position) : + RailVehicleClass::Instance {rvc->instances.acquire( + RailVehicleClass::commonLocationData.lock()->acquire(Location {.pos = position, .rot = {}}), + RailVehicleClass::commonLocationData.lock()->acquire( + Location {.pos = position + RelativePosition3D {0, rvc->wheelBase / 2.F, 0}, .rot = {}}), + RailVehicleClass::commonLocationData.lock()->acquire( + Location {.pos = position + RelativePosition3D {0, -rvc->wheelBase / 2.F, 0}, .rot = {}}))}, + rvClass {std::move(rvc)} { + lightsEnable(rvClass, get()->body.index); } void RailVehicle::move(const Train * t, float & trailBy) { const auto overhang {(rvClass->length - rvClass->wheelBase) / 2}; - const auto & b1Pos = bogies[0] = t->getBogiePosition(t->linkDist, trailBy += overhang); - const auto & b2Pos = bogies[1] = t->getBogiePosition(t->linkDist, trailBy += rvClass->wheelBase); - const auto diff = glm::normalize(RelativePosition3D(b2Pos.position() - b1Pos.position())); - location.setLocation((b1Pos.position() + b2Pos.position()) / 2, {vector_pitch(diff), vector_yaw(diff), 0}); + const auto & b1Pos = *(get()->front = t->getBogiePosition(t->linkDist, trailBy += overhang)); + const auto & b2Pos = *(get()->back = t->getBogiePosition(t->linkDist, trailBy += rvClass->wheelBase)); + const auto diff = glm::normalize(difference(b1Pos.position, b2Pos.position)); + get()->body = Location { + .pos = midpoint(b1Pos.position, b2Pos.position), .rot = {vector_pitch(diff), vector_yaw(diff), 0}}; trailBy += 600.F + overhang; } +Location +RailVehicle::getLocation() const +{ + return {.pos = get()->body->position, .rot = get()->body->rotation}; +} + bool RailVehicle::intersectRay(const Ray<GlobalPosition3D> & ray, BaryPosition & baryPos, RelativeDistance & distance) const { constexpr const auto X = 1350.F; const auto Y = this->rvClass->length / 2.F; constexpr const auto Z = 3900.F; - const glm::mat3 moveBy = location.getRotationTransform(); - const auto cornerVertices = cuboidCorners(-X, X, -Y, Y, 0.F, Z) * [&moveBy, this](const auto & corner) { - return location.position() + (moveBy * corner); - }; + const auto cornerVertices + = cuboidCorners(-X, X, -Y, Y, 0.F, Z) * [body = this->get()->body.get()](const auto & corner) { + return body->position + (body->rotationMatrix * corner); + }; static constexpr const std::array<glm::vec<3, uint8_t>, 10> triangles {{ // Front {0, 1, 2}, @@ -72,7 +70,12 @@ RailVehicle::intersectRay(const Ray<GlobalPosition3D> & ray, BaryPosition & bary }}; return std::any_of( triangles.begin(), triangles.end(), [&cornerVertices, &ray, &baryPos, &distance](const auto & idx) { - return ray.intersectTriangle( - cornerVertices[idx[0]], cornerVertices[idx[1]], cornerVertices[idx[2]], baryPos, distance); + if (const auto inter = ray.intersectTriangle( + cornerVertices[idx[0]], cornerVertices[idx[1]], cornerVertices[idx[2]])) { + baryPos = inter->bary; + distance = inter->distance; + return true; + }; + return false; }); } diff --git a/game/vehicles/railVehicle.h b/game/vehicles/railVehicle.h index bf1e782..c02c19e 100644 --- a/game/vehicles/railVehicle.h +++ b/game/vehicles/railVehicle.h @@ -1,8 +1,6 @@ #pragma once -#include "gfx/gl/bufferedLocation.h" #include "railVehicleClass.h" -#include <array> #include <game/selectable.h> #include <glm/glm.hpp> #include <memory> @@ -10,18 +8,16 @@ template<typename> class Ray; class Train; -class RailVehicle : Selectable, RailVehicleClass::Instance { +class RailVehicle : Selectable, RailVehicleClass::Instance, public InstanceLights { public: - explicit RailVehicle(RailVehicleClassPtr rvc); + explicit RailVehicle(RailVehicleClassPtr rvc, GlobalPosition3D = {}); void move(const Train *, float & trailBy); + [[nodiscard]] Location getLocation() const; [[nodiscard]] bool intersectRay(const Ray<GlobalPosition3D> &, BaryPosition &, RelativeDistance &) const override; RailVehicleClassPtr rvClass; - using LV = RailVehicleClass::LocationVertex; - BufferedLocationUpdater location; - std::array<BufferedLocationUpdater, 2> bogies; }; using RailVehiclePtr = std::unique_ptr<RailVehicle>; diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp index 34c1359..cfdc52d 100644 --- a/game/vehicles/railVehicleClass.cpp +++ b/game/vehicles/railVehicleClass.cpp @@ -1,7 +1,6 @@ #include "railVehicleClass.h" #include "gfx/gl/sceneShader.h" #include "gfx/gl/shadowMapper.h" -#include "gfx/gl/vertexArrayObject.h" #include <array> #include <glm/glm.hpp> #include <lib/resource.h> @@ -13,46 +12,62 @@ bool RailVehicleClass::persist(Persistence::PersistenceStore & store) { return STORE_TYPE && STORE_MEMBER(length) && STORE_MEMBER(wheelBase) && STORE_MEMBER(maxSpeed) - && STORE_NAME_HELPER("bogie", bogies, Asset::MeshArrayConstruct) + && STORE_NAME_HELPER("bogie", bogies, Asset::MeshArrayConstruct) && AssetLights::persist(store) && STORE_HELPER(bodyMesh, Asset::MeshConstruct) && Asset::persist(store); } +std::any +RailVehicleClass::createAt(const Location & position) const +{ + return std::make_shared<InstanceVertices<InstanceVertex>::InstanceProxy>(instances.acquire(InstanceVertex { + .body = locationData->acquire(position), + .front = locationData->acquire(position + ((sincos(position.rot.x) * wheelBase * 0.5F) || 0.F)), + .back = locationData->acquire(position + ((sincos(position.rot.x) * wheelBase * -0.5F) || 0.F)), + })); +} + void RailVehicleClass::postLoad() { texture = getTexture(); - bodyMesh->configureVAO(instanceVAO) - .addAttribs<LocationVertex, &LocationVertex::body, &LocationVertex::bodyPos>(instances.bufferName(), 1); - bogies.front() - ->configureVAO(instancesBogiesVAO.front()) - .addAttribs<LocationVertex, &LocationVertex::front, &LocationVertex::frontPos>(instances.bufferName(), 1); - bogies.back() - ->configureVAO(instancesBogiesVAO.back()) - .addAttribs<LocationVertex, &LocationVertex::back, &LocationVertex::backPos>(instances.bufferName(), 1); - static_assert(sizeof(LocationVertex) == 144UL); + glDebugScope _ {0}; + bodyMesh->configureVAO(instanceVAO, 0).addAttribs<InstanceVertex, &InstanceVertex::body>(1); +} + +void +RailVehicleClass::renderAllParts(const size_t count) const +{ + using PartPair = std::pair<Mesh::Ptr, CommonLocationInstance InstanceVertex::*>; + const auto bufferName = instances.bufferName(); + for (const auto & [mesh, part] : { + PartPair {bodyMesh, &InstanceVertex::body}, + PartPair {bogies.front(), &InstanceVertex::front}, + PartPair {bogies.back(), &InstanceVertex::back}, + }) { + instanceVAO.useBuffer<InstanceVertex>(1, bufferName, part); + mesh->drawInstanced(instanceVAO, static_cast<GLsizei>(count)); + } } void -RailVehicleClass::render(const SceneShader & shader) const +RailVehicleClass::render(const SceneShader & shader, const Frustum &) const { - if (const auto count = static_cast<GLsizei>(instances.size())) { + if (const auto count = (instances.size())) { + glDebugScope _ {instanceVAO}; if (texture) { - texture->bind(); + texture->bind(0); } shader.basicInst.use(); - 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 +RailVehicleClass::shadows(const ShadowMapper & mapper, const Frustum &) const { - if (const auto count = static_cast<GLsizei>(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 9d9d4c2..1ea87cd 100644 --- a/game/vehicles/railVehicleClass.h +++ b/game/vehicles/railVehicleClass.h @@ -1,46 +1,47 @@ #pragma once #include "assetFactory/asset.h" +#include "game/mixins/lights.h" #include "gfx/gl/instanceVertices.h" #include "gfx/models/mesh.h" +#include "gfx/models/texture.h" #include "gfx/renderable.h" #include <array> #include <memory> -#include <string> class SceneShader; class ShadowMapper; -class Texture; class Location; -class RailVehicleClass : public Renderable, public Asset { +class RailVehicleClass : public Renderable, public Asset, public AssetLights { public: - void render(const SceneShader & shader) const override; - void shadows(const ShadowMapper & shadowMapper) const override; + void render(const SceneShader & shader, const Frustum &) const override; + void shadows(const ShadowMapper & shadowMapper, const Frustum &) const override; - struct LocationVertex { - glm::mat3 body, front, back; - GlobalPosition3D bodyPos, frontPos, backPos; + [[nodiscard]] std::any createAt(const Location &) const override; + + struct InstanceVertex { + CommonLocationInstance body, front, back; }; std::array<Mesh::Ptr, 2> bogies; Mesh::Ptr bodyMesh; - std::shared_ptr<Texture> texture; + Texture::Ptr texture; float wheelBase; float length; float maxSpeed; - mutable InstanceVertices<LocationVertex> instances; + mutable InstanceVertices<InstanceVertex> instances; using Instance = decltype(instances)::InstanceProxy; protected: friend Persistence::SelectionPtrBase<std::shared_ptr<RailVehicleClass>>; bool persist(Persistence::PersistenceStore & store) override; void postLoad() override; + void renderAllParts(size_t count) const; private: glVertexArray instanceVAO; - std::array<glVertexArray, 2> instancesBogiesVAO; }; using RailVehicleClassPtr = std::shared_ptr<RailVehicleClass>; diff --git a/game/vehicles/train.cpp b/game/vehicles/train.cpp index 5bddd61..c79fd17 100644 --- a/game/vehicles/train.cpp +++ b/game/vehicles/train.cpp @@ -2,7 +2,6 @@ #include "game/vehicles/linkHistory.h" #include "game/vehicles/railVehicle.h" #include "game/vehicles/railVehicleClass.h" -#include "gfx/renderable.h" #include "location.h" #include <algorithm> #include <functional> @@ -11,6 +10,9 @@ template<typename> class Ray; +constexpr auto DECELERATION_RATE = 60000.F; +constexpr auto ACCELERATIONS_RATE = 30000.F; + Location Train::getBogiePosition(float linkDist, float dist) const { @@ -19,6 +21,12 @@ Train::getBogiePosition(float linkDist, float dist) const return b2Link.first->positionAt(b2linkDist, b2Link.second); } +Location +Train::getLocation() const +{ + return objects.front()->getLocation(); +} + bool Train::intersectRay(const Ray<GlobalPosition3D> & ray, BaryPosition & baryPos, RelativeDistance & distance) const { @@ -41,8 +49,8 @@ Train::doActivity(Go * go, TickDuration dur) const auto maxSpeed = objects.front()->rvClass->maxSpeed; if (go->dist) { *go->dist -= speed * dur.count(); - if (*go->dist < (speed * speed) / 60.F) { - speed -= std::min(speed, 30.F * dur.count()); + if (*go->dist < (speed * speed) / DECELERATION_RATE) { + speed -= std::min(speed, ACCELERATIONS_RATE * dur.count()); } else { if (speed != maxSpeed) { @@ -61,6 +69,6 @@ void Train::doActivity(Idle *, TickDuration dur) { if (speed != 0.F) { - speed -= std::min(speed, 30.F * dur.count()); + speed -= std::min(speed, DECELERATION_RATE * dur.count()); } } diff --git a/game/vehicles/train.h b/game/vehicles/train.h index 4320103..9ca53a8 100644 --- a/game/vehicles/train.h +++ b/game/vehicles/train.h @@ -15,16 +15,11 @@ class SceneShader; class ShadowMapper; template<typename> class Ray; -class Train : public Vehicle, public Collection<RailVehicle, false>, public Can<Go>, public Can<Idle> { +class Train : public Vehicle, public UniqueCollection<RailVehicle>, public Can<Go>, public Can<Idle> { public: - explicit Train(const Link::Ptr & link, float linkDist = 0) : Vehicle {link, linkDist} { } - - [[nodiscard]] const Location & - getLocation() const override - { - return objects.front()->location; - } + explicit Train(const Link::CPtr & link, float linkDist = 0) : Vehicle {link, linkDist} { } + [[nodiscard]] Location getLocation() const override; [[nodiscard]] bool intersectRay(const Ray<GlobalPosition3D> &, BaryPosition &, RelativeDistance &) const override; void tick(TickDuration elapsed) override; diff --git a/game/vehicles/vehicle.cpp b/game/vehicles/vehicle.cpp index 0d46017..dd652bc 100644 --- a/game/vehicles/vehicle.cpp +++ b/game/vehicles/vehicle.cpp @@ -15,7 +15,7 @@ #include <utility> #include <vector> -Vehicle::Vehicle(const Link::Ptr & l, float ld) : linkDist {ld} +Vehicle::Vehicle(const Link::CPtr & l, float ld) : linkDist {ld} { linkHist.add(l, 0); currentActivity = std::make_unique<Idle>(); diff --git a/game/vehicles/vehicle.h b/game/vehicles/vehicle.h index 354f904..cca8ff0 100644 --- a/game/vehicles/vehicle.h +++ b/game/vehicles/vehicle.h @@ -14,11 +14,11 @@ class Location; class Vehicle : public WorldObject, public Selectable { public: - explicit Vehicle(const Link::Ptr & link, float linkDist = 0); + explicit Vehicle(const Link::CPtr & link, float linkDist = 0); float linkDist; // distance along current link float speed {}; // speed in m/s (~75 km/h) - [[nodiscard]] virtual const Location & getLocation() const = 0; + [[nodiscard]] virtual Location getLocation() const = 0; Orders orders; ActivityPtr currentActivity; |
