mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 00:29:19 +02:00
184 lines
7.1 KiB
C++
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);
|
|
};
|