17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 00:29:19 +02:00
Files
maszyna/world/Sweep.h

184 lines
7.1 KiB
C++

/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <array>
#include <string>
#include <vector>
#include <glm/glm.hpp>
#include "utilities/Classes.h"
#include "utilities/Names.h"
#include "scene/scenenode.h"
#include "world/Road.h"
#include "world/Segment.h"
#include "vehicle/DynObj.h"
namespace scene
{
struct scratch_data;
}
// a model laid along a curve: copies of it bent to follow the curve end to end, or set along it at even steps.
// the node isn't drawn itself, it makes ordinary shapes of the copies, so the renderers deal with it as with the rest
// of the scenery. animations, lights and other submodels which aren't plain triangles are left out of the copies.
// scenery entry:
// node <max> <min> <name> sweep <model> <skin> [<property> <values>]... piece <laid out like a path of a track>... endsweep
// properties: mode <bend|repeat>, step <length of a copy along the curve, 0: the length of the model>,
// range <from> <to> (m along the curve, to below 0: up to its end), offset <sideways, + to the right> <up>,
// anchor <origin|near|far|centre> <origin|bottom|top> (what of the model the offset puts there: sideways its origin, its side
// facing the curve, the other side or its middle; up its origin, its bottom or its top),
// axis <x|z> (axis of the model laid along the curve), flip (the model goes the other way), mirror (its sides swapped),
// widen (the offset grows by the widening of the structure gauge in the curves, the way the platforms are set back),
// platform (as widen, and the copies stand on the plane of the rail heads carried on to the edge: lowered on the inner
// side of a canted curve, raised on the outer one),
// noface (the model isn't turned to have its -x side, or -z for one laid along x, facing the curve),
// parameters <count> <values>... (of a template: the model can be an *.inc file, its long models are bent, the others stand
// upright at their places along the curve),
// scale <x> <y> <z> (of the model, along its own axes), point <x> <y> <z> (a point of the model, in its own space, taken by the anchor point),
// anchor sides: origin, near, far, centre, point; heights: origin, bottom, top, edge (the top of the side facing the curve), point,
// tilt (bent copies lean with the cant of the curve; otherwise they stay upright, as the platforms and the walls by a track do,
// at the height the plane of the cant has at their sideways offset)
class sweep_node : public scene::basic_node
{
public:
struct state
{
std::string model;
std::string skin{"none"};
bool bend{true};
double step{0.0};
double from{0.0};
double to{-1.0};
double lateral{0.0};
double height{0.0};
bool along_x{false};
bool flip{false};
bool mirror{false};
bool tilt{false};
bool face{true}; // the model is turned so its -x side (-z for a model laid along x) faces the curve
bool widen{false}; // moved away from the curve by the widening of the structure gauge in the curves
bool platform{false}; // set back as widen does, and its height taken from the plane of the rail heads at its edge
std::vector<std::string> parameters; // of a template (*.inc) laid along the curve
int side_anchor{0}; // 0: origin, 1: the side facing the curve, 2: the far side, 3: the middle, 4: the point
int height_anchor{0}; // 0: origin, 1: bottom, 2: top, 3: top of the side facing the curve, 4: the point
glm::dvec3 point{0.0};
glm::dvec3 scale{1.0};
std::vector<segment_data> pieces;
bool operator==(state const &Other) const;
};
// point of the curve, with the directions the copies are laid out by
struct frame
{
glm::dvec3 position{0.0};
glm::dvec3 forward{0.0, 0.0, 1.0};
glm::dvec3 left{-1.0, 0.0, 0.0};
glm::dvec3 up{0.0, 1.0, 0.0};
double roll{0.0}; // degrees, of the curve there
std::array<double, 2> widening{}; // of the structure gauge, below the platforms: right and left side, metres
std::array<double, 2> cant{}; // metres, positive on the inner side of the curve
};
explicit sweep_node(scene::node_data const &Nodedata);
void import(cParser &Input, glm::dvec3 const &Offset);
void define(state const &State);
state const &definition() const
{
return m_state;
}
// length of the curve, in the plan
double length() const;
frame frame_at(double const Station) const;
// station of the point of the curve nearest to the point in the plan, and how far to the right of the curve it is
double project(glm::dvec3 const &Point, double &Lateral) const;
// stretch of the curve the copies take
double start() const;
double end() const;
// length of a copy along the curve, as the model has it
double model_length() const;
bool bounds(glm::dvec3 &Low, glm::dvec3 &High, glm::dvec3 &Shift) const;
bool edge_far() const;
glm::dvec3 axes(glm::dvec3 const &Vector) const;
double distance_at(double const Station) const;
double station_at(double const Distance) const;
double setback(frame const &At) const;
// height the copies stand at over the points of the curve, less the height of the rail: the head of the rail on their side,
// for a platform the plane of the rail heads carried on to its edge, lower on the inner side of a canted curve
double rise(frame const &At) const;
std::vector<scene::shape_node> create_shapes() const;
// a model of what's laid along the curve, placed in its space
struct item
{
TModel3d *model{nullptr};
material_data skins;
glm::dmat4 transform{1.0};
};
std::vector<item> items() const;
// height of the head of the rail on the side of the offset over the points of the track, less the height of the rail
static double rail_head(double const Roll, double const Lateral);
// puts the copies in the scene as shapes of their own, which can be taken back
void show();
void hide();
void refresh();
bool bridge();
void merged(bool const Merged)
{
m_merged = Merged;
}
bool merged() const
{
return m_merged;
}
bool m_editorremoved{false};
private:
void rebuild_samples();
float radius_() override;
void serialize_(std::ostream &Output) const override;
void deserialize_(std::istream &Input) override;
void export_as_text_(std::ostream &Output) const override;
struct sample
{
double station;
glm::dvec3 position;
glm::dvec3 tangent;
double roll; // degrees
std::array<double, 2> widening;
std::array<double, 2> cant;
};
static void sample_piece(segment_data const &Piece, std::vector<sample> &Samples, double &Station);
static void gauge_along(std::vector<sample> &Samples);
void beside_switches(std::vector<sample> &Samples);
state m_state;
std::vector<sample> m_samples;
std::vector<double> m_distances;
mutable bool m_boundsvalid{false};
mutable bool m_boundsfound{false};
mutable bool m_edgefar{false};
mutable glm::dvec3 m_low{0.0}, m_high{0.0}, m_shift{0.0};
bool m_merged{false};
owned_shapes m_shapes;
};
// collection of the models laid along curves present in the scene
class sweep_table : public basic_table<sweep_node>
{
public:
// generates geometry of the copies and puts it in the scene
void create_geometry(scene::scratch_data &Scratchpad);
};