/* 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 #include #include #include #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 sweep [ ]... piece ... endsweep // properties: mode , step , // range (m along the curve, to below 0: up to its end), offset , // anchor (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 (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 ... (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 (of the model, along its own axes), point (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 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 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 widening{}; // of the structure gauge, below the platforms: right and left side, metres std::array 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 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 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 widening; std::array cant; }; static void sample_piece(segment_data const &Piece, std::vector &Samples, double &Station); static void gauge_along(std::vector &Samples); void beside_switches(std::vector &Samples); state m_state; std::vector m_samples; std::vector 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 { public: // generates geometry of the copies and puts it in the scene void create_geometry(scene::scratch_data &Scratchpad); };