summaryrefslogtreecommitdiff
path: root/game/vehicles/railVehicle.cpp
blob: bee0dd0d9325a421abcc363373937982bbb4956e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "railVehicle.h"
#include "railVehicleClass.h"
#include "train.h"
#include <algorithm>
#include <array>
#include <glm/glm.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtx/transform.hpp>
#include <location.h>
#include <maths.h>
#include <memory>
#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();
			 },
					Position3D {0, rvClass->wheelBase / 2.F, 0}},
			{[this](const BufferedLocation * l) {
				 this->get()->back = l->getRotationTransform();
				 this->get()->backPos = l->position();
			 },
					Position3D {0, -rvClass->wheelBase / 2.F, 0}},
	}}
{
}

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.position() - b1Pos.position());
	location.setLocation((b1Pos.position() + b2Pos.position()) / 2.F, {vector_pitch(diff), vector_yaw(diff), 0});
	trailBy += 0.6F + overhang;
}

bool
RailVehicle::intersectRay(const Ray & ray, Position2D * baryPos, float * distance) const
{
	constexpr const auto X = 1350.F;
	const auto Y = this->rvClass->length / 2.F;
	constexpr const auto Z = 3900.F;
	const auto moveBy = location.getRotationTransform();
	const std::array<Position3D, 8> cornerVertices {{
			location.position() + (moveBy * glm::vec4 {-X, Y, 0, 1}).xyz(), //  LFB
			location.position() + (moveBy * glm::vec4 {X, Y, 0, 1}).xyz(), //   RFB
			location.position() + (moveBy * glm::vec4 {-X, Y, Z, 1}).xyz(), //  LFT
			location.position() + (moveBy * glm::vec4 {X, Y, Z, 1}).xyz(), //   RFT
			location.position() + (moveBy * glm::vec4 {-X, -Y, 0, 1}).xyz(), // LBB
			location.position() + (moveBy * glm::vec4 {X, -Y, 0, 1}).xyz(), //  RBB
			location.position() + (moveBy * glm::vec4 {-X, -Y, Z, 1}).xyz(), // LBT
			location.position() + (moveBy * glm::vec4 {X, -Y, Z, 1}).xyz(), //  RBT
	}};
	static constexpr const std::array<glm::vec<3, uint8_t>, 10> triangles {{
			// Front
			{0, 1, 2},
			{1, 2, 3},
			// Left
			{0, 2, 4},
			{2, 4, 6},
			// Back
			{4, 5, 6},
			{5, 6, 7},
			// Right
			{1, 3, 5},
			{3, 5, 7},
			// Top
			{2, 3, 6},
			{3, 6, 7},
	}};
	return std::any_of(
			triangles.begin(), triangles.end(), [&cornerVertices, &ray, &baryPos, &distance](const auto & idx) {
				return glm::intersectRayTriangle(ray.start, ray.direction, cornerVertices[idx[0]],
						cornerVertices[idx[1]], cornerVertices[idx[2]], *baryPos, *distance);
			});
}