From e118b1f5d8071460e3a9d4d731c6d69221f785dc Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 6 Mar 2021 19:44:58 +0000 Subject: Carve up the mess in game/vehicles --- game/vehicles/linkHistory.cpp | 41 +++++++++++ game/vehicles/linkHistory.h | 21 ++++++ game/vehicles/railVehicle.cpp | 26 +++++++ game/vehicles/railVehicle.h | 29 ++++++++ game/vehicles/railVehicleClass.cpp | 80 ++++++++++++++++++++ game/vehicles/railVehicleClass.h | 33 +++++++++ game/vehicles/railloco.cpp | 146 ------------------------------------- game/vehicles/railloco.h | 69 ------------------ game/vehicles/train.cpp | 60 +++++++++++++++ game/vehicles/train.h | 33 +++++++++ game/vehicles/vehicle.cpp | 41 +---------- game/vehicles/vehicle.h | 16 +--- 12 files changed, 325 insertions(+), 270 deletions(-) create mode 100644 game/vehicles/linkHistory.cpp create mode 100644 game/vehicles/linkHistory.h create mode 100644 game/vehicles/railVehicle.cpp create mode 100644 game/vehicles/railVehicle.h create mode 100644 game/vehicles/railVehicleClass.cpp create mode 100644 game/vehicles/railVehicleClass.h delete mode 100644 game/vehicles/railloco.cpp delete mode 100644 game/vehicles/railloco.h create mode 100644 game/vehicles/train.cpp create mode 100644 game/vehicles/train.h (limited to 'game') diff --git a/game/vehicles/linkHistory.cpp b/game/vehicles/linkHistory.cpp new file mode 100644 index 0000000..4fac4ba --- /dev/null +++ b/game/vehicles/linkHistory.cpp @@ -0,0 +1,41 @@ +#include "linkHistory.h" +#include "game/network/link.h" +#include + +LinkHistory::Entry +LinkHistory::add(const LinkWPtr & l, unsigned char d) +{ + links.insert(links.begin(), {l, d}); + const auto lp = l.lock(); + totalLen += lp->length; + while (totalLen >= 1000.F && !links.empty()) { + totalLen -= links.back().first.lock()->length; + links.pop_back(); + } + return {lp, d}; +} + +LinkHistory::Entry +LinkHistory::getCurrent() const +{ + return {links.front().first.lock(), links.front().second}; +} + +LinkHistory::Entry +LinkHistory::getAt(float len, float * rem) const +{ + auto litr = links.begin(); + while (len > 0.F && litr != links.end()) { + litr++; + if (litr != links.end()) { + len -= litr->first.lock()->length; + } + } + if (litr == links.end()) { + litr--; + } + if (rem) { + *rem = -len; + } + return {litr->first.lock(), litr->second}; +} diff --git a/game/vehicles/linkHistory.h b/game/vehicles/linkHistory.h new file mode 100644 index 0000000..31d0023 --- /dev/null +++ b/game/vehicles/linkHistory.h @@ -0,0 +1,21 @@ +#ifndef LINKHISTORY_H +#define LINKHISTORY_H + +#include +#include +#include + +class LinkHistory { +public: + using WEntry = std::pair; + using Entry = std::pair; + Entry add(const LinkWPtr &, unsigned char); + [[nodiscard]] Entry getCurrent() const; + [[nodiscard]] Entry getAt(float, float *) const; + +private: + std::vector links; + float totalLen {0.F}; +}; + +#endif diff --git a/game/vehicles/railVehicle.cpp b/game/vehicles/railVehicle.cpp new file mode 100644 index 0000000..a2373e7 --- /dev/null +++ b/game/vehicles/railVehicle.cpp @@ -0,0 +1,26 @@ +#include "railVehicle.h" +#include "railVehicleClass.h" +#include "train.h" +#include +#include +#include +#include +#include + +void +RailVehicle::render(const Shader & shader) const +{ + rvClass->render(shader, location, bogies); +} + +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(b2Pos.pos - b1Pos.pos); + location.pos = (b1Pos.pos + b2Pos.pos) / 2.F; + location.rot = {-vector_pitch(diff), vector_yaw(diff), 0}; + trailBy += 0.6F + overhang; +} diff --git a/game/vehicles/railVehicle.h b/game/vehicles/railVehicle.h new file mode 100644 index 0000000..a089f1d --- /dev/null +++ b/game/vehicles/railVehicle.h @@ -0,0 +1,29 @@ +#ifndef RAILVEHICLE_H +#define RAILVEHICLE_H + +#include "gfx/renderable.h" +#include "railVehicleClass.h" +#include +#include +#include +#include + +class Shader; + +class Train; +class RailVehicle : public Renderable { +public: + explicit RailVehicle(RailVehicleClassPtr rvc) : rvClass {std::move(rvc)} { } + + void move(const Train *, float & trailBy); + + void render(const Shader & shader) const override; + + Location location; + + RailVehicleClassPtr rvClass; + std::array bogies; +}; +using RailVehiclePtr = std::unique_ptr; + +#endif diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp new file mode 100644 index 0000000..71890b8 --- /dev/null +++ b/game/vehicles/railVehicleClass.cpp @@ -0,0 +1,80 @@ +#include "railVehicleClass.h" +#include "gfx/gl/shader.h" +#include "gfx/models/mesh.h" +#include "gfx/models/obj.h" +#include "gfx/models/texture.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +RailVehicleClass::RailVehicleClass(const std::string & name) : + RailVehicleClass {std::make_unique(Resource::mapPath(name + ".obj")), + Texture::cachedTexture.get(Resource::mapPath(name + ".png"))} +{ +} + +RailVehicleClass::RailVehicleClass(std::unique_ptr o, std::shared_ptr t) : texture {std::move(t)} +{ + wheelBase = bogieOffset(*o); + length = objectLength(*o); + const auto m = o->createMeshes(); + bodyMesh = m.at("Body"); + bogies[0] = m.at("Bogie1"); + bogies[1] = m.at("Bogie2"); +} + +void +RailVehicleClass::render(const Shader & shader, const Location & location, const std::array & bl) const +{ + texture->Bind(); + for (auto b = 0U; b < bogies.size(); ++b) { + shader.setModel(bl[b]); + bogies[b]->Draw(); + } + shader.setModel(location); + bodyMesh->Draw(); +} + +float +RailVehicleClass::bogieOffset(ObjParser & o) +{ + float wheelBase {0}; + // offset bogie positions so they can be set directly + for (auto & object : o.objects) { // bogie object index + if (!object.first.starts_with("Bogie")) { + continue; + } + std::set> vertexIds; + for (const auto & face : object.second) { + for (const auto & faceElement : face) { + vertexIds.emplace(o.vertices[faceElement.x - 1].z, faceElement.x - 1); + } + } + const auto offset = (vertexIds.begin()->first + vertexIds.rbegin()->first) / 2; + for (const auto & v : vertexIds) { + o.vertices[v.second].z -= offset; + } + wheelBase += std::abs(offset); + } + return wheelBase; +} + +float +RailVehicleClass::objectLength(ObjParser & o) +{ + const auto mme = std::minmax_element(o.vertices.begin(), o.vertices.end(), [](const auto & v1, const auto & v2) { + return v1.z < v2.z; + }); + return mme.second->z - mme.first->z; +} diff --git a/game/vehicles/railVehicleClass.h b/game/vehicles/railVehicleClass.h new file mode 100644 index 0000000..b902367 --- /dev/null +++ b/game/vehicles/railVehicleClass.h @@ -0,0 +1,33 @@ +#ifndef RAILVEHICLECLASS_H +#define RAILVEHICLECLASS_H + +#include "gfx/models/mesh.h" +#include +#include +#include + +class Shader; +class Texture; +class ObjParser; +class Location; + +class RailVehicleClass { +public: + explicit RailVehicleClass(const std::string & name); + + void render(const Shader &, const Location &, const std::array &) const; + + std::array bogies; + MeshPtr bodyMesh; + std::shared_ptr texture; + float wheelBase; + float length; + +private: + RailVehicleClass(std::unique_ptr obj, std::shared_ptr); + static float bogieOffset(ObjParser & o); + static float objectLength(ObjParser & o); +}; +using RailVehicleClassPtr = std::shared_ptr; + +#endif diff --git a/game/vehicles/railloco.cpp b/game/vehicles/railloco.cpp deleted file mode 100644 index 6745c8f..0000000 --- a/game/vehicles/railloco.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include "railloco.h" -#include "gfx/gl/shader.h" -#include "gfx/models/obj.h" -#include "gfx/models/texture.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -RailVehicleClass::RailVehicleClass(const std::string & name) : - RailVehicleClass {std::make_unique(Resource::mapPath(name + ".obj")), - Texture::cachedTexture.get(Resource::mapPath(name + ".png"))} -{ -} - -RailVehicleClass::RailVehicleClass(std::unique_ptr o, std::shared_ptr t) : texture {std::move(t)} -{ - wheelBase = bogieOffset(*o); - length = objectLength(*o); - const auto m = o->createMeshes(); - bodyMesh = m.at("Body"); - bogies[0] = m.at("Bogie1"); - bogies[1] = m.at("Bogie2"); -} - -void -RailVehicleClass::render(const Shader & shader, const Location & location, const std::array & bl) const -{ - texture->Bind(); - for (auto b = 0U; b < bogies.size(); ++b) { - shader.setModel(bl[b]); - bogies[b]->Draw(); - } - shader.setModel(location); - bodyMesh->Draw(); -} - -float -RailVehicleClass::bogieOffset(ObjParser & o) -{ - float wheelBase {0}; - // offset bogie positions so they can be set directly - for (auto & object : o.objects) { // bogie object index - if (!object.first.starts_with("Bogie")) { - continue; - } - std::set> vertexIds; - for (const auto & face : object.second) { - for (const auto & faceElement : face) { - vertexIds.emplace(o.vertices[faceElement.x - 1].z, faceElement.x - 1); - } - } - const auto offset = (vertexIds.begin()->first + vertexIds.rbegin()->first) / 2; - for (const auto & v : vertexIds) { - o.vertices[v.second].z -= offset; - } - wheelBase += std::abs(offset); - } - return wheelBase; -} - -float -RailVehicleClass::objectLength(ObjParser & o) -{ - const auto mme = std::minmax_element(o.vertices.begin(), o.vertices.end(), [](const auto & v1, const auto & v2) { - return v1.z < v2.z; - }); - return mme.second->z - mme.first->z; -} - -void -RailVehicle::render(const Shader & shader) const -{ - rvClass->render(shader, location, bogies); -} - -void -Train::move(TickDuration dur) -{ - static std::mt19937 gen(std::random_device {}()); - linkDist += dur.count() * speed; - auto curLink {linkHist.getCurrent()}; - while (linkDist > curLink.first->length) { - const auto location = curLink.first->positionAt(curLink.first->length, curLink.second); - auto nexts {curLink.first->nexts[1 - curLink.second]}; - auto last = std::remove_if(nexts.begin(), nexts.end(), [ang = location.rot.y](const Link::Next & n) { - return std::abs(normalize(n.first.lock()->ends[n.second].second - ang)) > 0.1F; - }); - if (last != nexts.begin()) { - auto off = std::uniform_int_distribution<>(0, std::distance(nexts.begin(), last) - 1)(gen); - linkDist -= curLink.first->length; - curLink = linkHist.add(nexts[off].first, nexts[off].second); - } - else { - linkDist = curLink.first->length; - speed = 0; - } - } -} - -void -Train::render(const Shader & shader) const -{ - apply(&Renderable::render, shader); -} - -Location -Train::getBogiePosition(float linkDist, float dist) const -{ - float b2linkDist {}; - const auto b2Link = linkHist.getAt(dist - linkDist, &b2linkDist); - return b2Link.first->positionAt(b2linkDist, b2Link.second); -} - -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(b2Pos.pos - b1Pos.pos); - location.pos = (b1Pos.pos + b2Pos.pos) / 2.F; - location.rot = {-vector_pitch(diff), vector_yaw(diff), 0}; - trailBy += 0.6F + overhang; -} - -void -Train::tick(TickDuration dur) -{ - move(dur); - - float trailBy {0.F}; - apply(&RailVehicle::move, this, std::ref(trailBy)); -} diff --git a/game/vehicles/railloco.h b/game/vehicles/railloco.h deleted file mode 100644 index 0f240e2..0000000 --- a/game/vehicles/railloco.h +++ /dev/null @@ -1,69 +0,0 @@ -#include "game/network/link.h" -#include "game/vehicles/vehicle.h" -#include "game/worldobject.h" -#include "gfx/models/mesh.h" -#include "gfx/renderable.h" -#include -#include -#include -#include -#include -#include -#include - -class Shader; -class Texture; -class ObjParser; - -class RailVehicleClass { -public: - explicit RailVehicleClass(const std::string & name); - - void render(const Shader &, const Location &, const std::array &) const; - - std::array bogies; - MeshPtr bodyMesh; - std::shared_ptr texture; - float wheelBase; - float length; - -private: - RailVehicleClass(std::unique_ptr obj, std::shared_ptr); - static float bogieOffset(ObjParser & o); - static float objectLength(ObjParser & o); -}; -using RailVehicleClassPtr = std::shared_ptr; - -class Train; -class RailVehicle : public Renderable { -public: - explicit RailVehicle(RailVehicleClassPtr rvc) : rvClass {std::move(rvc)} { } - - void move(const Train *, float & trailBy); - - void render(const Shader & shader) const override; - - Location location; - - RailVehicleClassPtr rvClass; - std::array bogies; -}; -using RailVehiclePtr = std::unique_ptr; - -class Train : public Vehicle, public Collection { -public: - explicit Train(const LinkPtr & link, float linkDist = 0) : Vehicle {link, linkDist} { } - - [[nodiscard]] const Location & - getLocation() const override - { - return objects.front()->location; - } - - void render(const Shader & shader) const override; - - void tick(TickDuration elapsed) override; - - void move(TickDuration dur); - [[nodiscard]] Location getBogiePosition(float linkDist, float dist) const; -}; diff --git a/game/vehicles/train.cpp b/game/vehicles/train.cpp new file mode 100644 index 0000000..e211f16 --- /dev/null +++ b/game/vehicles/train.cpp @@ -0,0 +1,60 @@ +#include "train.h" +#include "game/vehicles/linkHistory.h" +#include "game/vehicles/railVehicle.h" +#include "gfx/renderable.h" +#include "location.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +void +Train::move(TickDuration dur) +{ + static std::mt19937 gen(std::random_device {}()); + linkDist += dur.count() * speed; + auto curLink {linkHist.getCurrent()}; + while (linkDist > curLink.first->length) { + const auto location = curLink.first->positionAt(curLink.first->length, curLink.second); + auto nexts {curLink.first->nexts[1 - curLink.second]}; + auto last = std::remove_if(nexts.begin(), nexts.end(), [ang = location.rot.y](const Link::Next & n) { + return std::abs(normalize(n.first.lock()->ends[n.second].second - ang)) > 0.1F; + }); + if (last != nexts.begin()) { + auto off = std::uniform_int_distribution<>(0, std::distance(nexts.begin(), last) - 1)(gen); + linkDist -= curLink.first->length; + curLink = linkHist.add(nexts[off].first, nexts[off].second); + } + else { + linkDist = curLink.first->length; + speed = 0; + } + } +} + +void +Train::render(const Shader & shader) const +{ + apply(&Renderable::render, shader); +} + +Location +Train::getBogiePosition(float linkDist, float dist) const +{ + float b2linkDist {}; + const auto b2Link = linkHist.getAt(dist - linkDist, &b2linkDist); + return b2Link.first->positionAt(b2linkDist, b2Link.second); +} + +void +Train::tick(TickDuration dur) +{ + move(dur); + + float trailBy {0.F}; + apply(&RailVehicle::move, this, std::ref(trailBy)); +} diff --git a/game/vehicles/train.h b/game/vehicles/train.h new file mode 100644 index 0000000..34a9d28 --- /dev/null +++ b/game/vehicles/train.h @@ -0,0 +1,33 @@ +#ifndef TRAIN_H +#define TRAIN_H + +#include "game/network/link.h" +#include "game/worldobject.h" +#include "railVehicle.h" +#include "vehicle.h" +#include +#include +#include +#include + +class Shader; + +class Train : public Vehicle, public Collection { +public: + explicit Train(const LinkPtr & link, float linkDist = 0) : Vehicle {link, linkDist} { } + + [[nodiscard]] const Location & + getLocation() const override + { + return objects.front()->location; + } + + void render(const Shader & shader) const override; + + void tick(TickDuration elapsed) override; + + void move(TickDuration dur); + [[nodiscard]] Location getBogiePosition(float linkDist, float dist) const; +}; + +#endif diff --git a/game/vehicles/vehicle.cpp b/game/vehicles/vehicle.cpp index 26e33d4..d98533e 100644 --- a/game/vehicles/vehicle.cpp +++ b/game/vehicles/vehicle.cpp @@ -1,47 +1,8 @@ #include "vehicle.h" #include "game/network/link.h" -#include -#include +#include "game/vehicles/linkHistory.h" Vehicle::Vehicle(const LinkPtr & l, float ld) : linkDist {ld} { linkHist.add(l, 0); } - -LinkHistory::Entry -LinkHistory::add(const LinkWPtr & l, unsigned char d) -{ - links.insert(links.begin(), {l, d}); - const auto lp = l.lock(); - totalLen += lp->length; - while (totalLen >= 1000.F && !links.empty()) { - totalLen -= links.back().first.lock()->length; - links.pop_back(); - } - return {lp, d}; -} - -LinkHistory::Entry -LinkHistory::getCurrent() const -{ - return {links.front().first.lock(), links.front().second}; -} - -LinkHistory::Entry -LinkHistory::getAt(float len, float * rem) const -{ - auto litr = links.begin(); - while (len > 0.F && litr != links.end()) { - litr++; - if (litr != links.end()) { - len -= litr->first.lock()->length; - } - } - if (litr == links.end()) { - litr--; - } - if (rem) { - *rem = -len; - } - return {litr->first.lock(), litr->second}; -} diff --git a/game/vehicles/vehicle.h b/game/vehicles/vehicle.h index 89a6901..659821f 100644 --- a/game/vehicles/vehicle.h +++ b/game/vehicles/vehicle.h @@ -1,28 +1,14 @@ #ifndef VEHICLE_H #define VEHICLE_H +#include "linkHistory.h" #include #include #include #include -#include -#include class Location; -class LinkHistory { -public: - using WEntry = std::pair; - using Entry = std::pair; - Entry add(const LinkWPtr &, unsigned char); - [[nodiscard]] Entry getCurrent() const; - [[nodiscard]] Entry getAt(float, float *) const; - -private: - std::vector links; - float totalLen {0.F}; -}; - class Vehicle : public WorldObject, public Renderable { public: explicit Vehicle(const LinkPtr & link, float linkDist = 0); -- cgit v1.2.3