summaryrefslogtreecommitdiff
path: root/game/vehicles
diff options
context:
space:
mode:
Diffstat (limited to 'game/vehicles')
-rw-r--r--game/vehicles/linkHistory.cpp18
-rw-r--r--game/vehicles/railVehicle.cpp59
-rw-r--r--game/vehicles/railVehicle.h10
-rw-r--r--game/vehicles/railVehicleClass.cpp59
-rw-r--r--game/vehicles/railVehicleClass.h23
-rw-r--r--game/vehicles/train.cpp16
-rw-r--r--game/vehicles/train.h11
-rw-r--r--game/vehicles/vehicle.cpp2
-rw-r--r--game/vehicles/vehicle.h4
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;