/* 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 "Classes.h" #include "material.h" #include "dumb3d.h" #include "Names.h" #include "lightarray.h" #include "simulation.h" typedef int TGroundNodeType; // Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie const int TP_MODEL = 10; /* const int TP_MESH = 11; // Ra: specjalny obiekt grupujący siatki dla tekstury const int TP_DUMMYTRACK = 12; // Ra: zdublowanie obiektu toru dla rozdzielenia tekstur */ const int TP_TERRAIN = 13; // Ra: specjalny model dla terenu const int TP_DYNAMIC = 14; const int TP_SOUND = 15; const int TP_TRACK = 16; /* const int TP_GEOMETRY=17; */ const int TP_MEMCELL = 18; const int TP_EVLAUNCH = 19; // MC const int TP_TRACTION = 20; const int TP_TRACTIONPOWERSOURCE = 21; // MC /* const int TP_ISOLATED=22; //Ra */ const int TP_SUBMODEL = 22; // Ra: submodele terenu const int TP_LAST = 25; // rozmiar tablicy struct TGroundVertex { glm::dvec3 position; glm::vec3 normal; glm::vec2 texture; void HalfSet(const TGroundVertex &v1, const TGroundVertex &v2) { // wyliczenie współrzędnych i mapowania punktu na środku odcinka v1<->v2 interpolate_( v1, v2, 0.5 ); } void SetByX(const TGroundVertex &v1, const TGroundVertex &v2, double x) { // wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2 interpolate_( v1, v2, ( x - v1.position.x ) / ( v2.position.x - v1.position.x ) ); } void SetByZ(const TGroundVertex &v1, const TGroundVertex &v2, double z) { // wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2 interpolate_( v1, v2, ( z - v1.position.z ) / ( v2.position.z - v1.position.z ) ); } void interpolate_( const TGroundVertex &v1, const TGroundVertex &v2, double factor ) { position = interpolate( v1.position, v2.position, factor ); normal = interpolate( v1.normal, v2.normal, static_cast( factor ) ); texture = interpolate( v1.texture, v2.texture, static_cast( factor ) ); } }; // ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node struct piece_node { std::vector vertices; geometry_handle geometry { 0, 0 }; // geometry prepared for drawing }; // obiekt scenerii class TGroundNode { friend class opengl_renderer; public: TGroundNode *nNext; // lista wszystkich w scenerii, ostatni na początku TGroundNode *nNext2; // lista obiektów w sektorze TGroundNode *nNext3; // lista obiektów renderowanych we wspólnym cyklu std::string asName; // nazwa (nie zawsze ma znaczenie) TGroundNodeType iType; // typ obiektu union { // Ra: wskażniki zależne od typu - zrobić klasy dziedziczone zamiast void *Pointer; // do przypisywania NULL TSubModel *smTerrain; // modele terenu (kwadratow kilometrowych) TAnimModel *Model; // model z animacjami TDynamicObject *DynamicObject; // pojazd piece_node *Piece; // non-instanced piece of geometry TTrack *pTrack; // trajektoria ruchu TMemCell *MemCell; // komórka pamięci TEventLauncher *EvLaunch; // wyzwalacz zdarzeń TTraction *hvTraction; // drut zasilający TTractionPowerSource *psTractionPowerSource; // zasilanie drutu (zaniedbane w sceneriach) TTextSound *tsStaticSound; // dźwięk przestrzenny TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów }; Math3D::vector3 pCenter; // współrzędne środka do przydzielenia sektora float m_radius { 0.0f }; // bounding radius of geometry stored in the node. TODO: reuse bounding_area struct for radius and center glm::dvec3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world // visualization-related data // TODO: wrap these in a struct, when cleaning objects up double fSquareMinRadius; // kwadrat widoczności od double fSquareRadius; // kwadrat widoczności do union { int iNumVerts; // dla trójkątów int iNumPts; // dla linii int iCount; // dla terenu }; int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany material_handle m_material; // główna (jedna) tekstura obiektu glm::vec3 Ambient{ 0.2f }, Diffuse{ 1.0f }, Specular{ 0.0f }; // oświetlenie double fLineThickness; // McZapkie-120702: grubosc linii bool bVisible; TGroundNode(); TGroundNode(TGroundNodeType t); ~TGroundNode(); void InitNormals(); void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń }; class TSubRect : public CMesh { // sektor składowy kwadratu kilometrowego public: scene::bounding_area m_area; unsigned int m_framestamp { 0 }; // id of last rendered gfx frame int iTracks = 0; // ilość torów w (tTracks) TTrack **tTracks = nullptr; // tory do renderowania pojazdów protected: TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji public: TGroundNode *nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2) TGroundNode *nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3) TGroundNode *nRenderRect = nullptr; // z poziomu sektora - nieprzezroczyste (nNext3) TGroundNode *nRenderRectAlpha = nullptr; // z poziomu sektora - przezroczyste (nNext3) TGroundNode *nRenderWires = nullptr; // z poziomu sektora - druty i inne linie (nNext3) TGroundNode *nRender = nullptr; // indywidualnie - nieprzezroczyste (nNext3) TGroundNode *nRenderMixed = nullptr; // indywidualnie - nieprzezroczyste i przezroczyste (nNext3) TGroundNode *nRenderAlpha = nullptr; // indywidualnie - przezroczyste (nNext3) #ifdef EU07_SCENERY_EDITOR std::deque< TGroundNode* > m_memcells; // collection of memcells present in the sector #endif int iNodeCount = 0; // licznik obiektów, do pomijania pustych sektorów public: void LoadNodes(); // utworzenie VBO sektora public: virtual ~TSubRect(); virtual void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur) TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude); TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude); #ifdef EU07_USE_OLD_GROUNDCODE bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji torów void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów #endif }; // Ra: trzeba sprawdzić wydajność siatki const int iNumSubRects = 5; // na ile dzielimy kilometr const int iNumRects = 500; const int iTotalNumSubRects = iNumRects * iNumSubRects; const double fHalfTotalNumSubRects = iTotalNumSubRects / 2.0; const double fSubRectSize = 1000.0 / iNumSubRects; const double fRectSize = fSubRectSize * iNumSubRects; class TGroundRect : public TSubRect { // kwadrat kilometrowy // obiekty o niewielkiej ilości wierzchołków będą renderowane stąd // Ra: 2012-02 doszły submodele terenu friend class opengl_renderer; private: TSubRect *pSubRects { nullptr }; void Init(); public: virtual ~TGroundRect(); // pobranie wskaźnika do małego kwadratu, utworzenie jeśli trzeba inline TSubRect * SafeGetSubRect(int iCol, int iRow) { if( !pSubRects ) { // utworzenie małych kwadratów Init(); } return pSubRects + iRow * iNumSubRects + iCol; // zwrócenie właściwego }; // pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma inline TSubRect *FastGetSubRect(int iCol, int iRow) const { return ( pSubRects ? pSubRects + iRow * iNumSubRects + iCol : nullptr); }; void NodeAdd( TGroundNode *Node ); // dodanie obiektu do sektora na etapie rozdzielania na sektory // compares two provided nodes, returns true if their content can be merged bool mergeable( TGroundNode const &Left, TGroundNode const &Right ) const; // optymalizacja obiektów w sektorach inline void Optimize() { if( pSubRects ) { for( int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i ) { // optymalizacja obiektów w sektorach pSubRects[ i ].Sort(); } } }; TGroundNode *nTerrain { nullptr }; // model terenu z E3D - użyć nRootMesh? }; class TGround { friend class opengl_renderer; TGroundRect Rects[ iNumRects ][ iNumRects ]; // mapa kwadratów kilometrowych TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe) TGroundNode *nRootDynamic = nullptr; // lista pojazdów TGroundNode *nRootOfType[ TP_LAST ]; // tablica grupująca obiekty, przyspiesza szukanie #ifdef EU07_USE_OLD_GROUNDCODE TEvent *RootEvent = nullptr; // lista zdarzeń TEvent *QueryRootEvent = nullptr, *tmpEvent = nullptr; typedef std::unordered_map event_map; event_map m_eventmap; TNames m_nodemap; #endif vector3 pOrigin; vector3 aRotate; bool bInitDone = false; private: // metody prywatne #ifdef EU07_USE_OLD_GROUNDCODE bool EventConditon(TEvent *e); #endif public: TGround(); ~TGround(); void Free(); #ifdef EU07_USE_OLD_GROUNDCODE bool Init( std::string File ); void FirstInit(); void InitTracks(); void InitTraction(); bool InitEvents(); bool InitLaunchers(); TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude); TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TGroundNode *Exclude); TTraction * TractionNearestFind(glm::dvec3 &p, int dir, TGroundNode *n); #endif TGroundNode * AddGroundNode(cParser *parser); #ifdef EU07_USE_OLD_GROUNDCODE void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS void Update_Hidden(); // updates invisible elements of the scene bool GetTraction(TDynamicObject *model); bool AddToQuery( TEvent *Event, TDynamicObject *Node ); bool CheckQuery(); TGroundNode * DynamicFindAny(std::string const &Name); TGroundNode * DynamicFind(std::string const &Name); TGroundNode * FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType); #endif TGroundRect * GetRect( double x, double z ); TSubRect * GetSubRect( int iCol, int iRow ); inline TSubRect * GetSubRect(double x, double z) { return GetSubRect(GetColFromX(x), GetRowFromZ(z)); }; TSubRect * FastGetSubRect( int iCol, int iRow ); inline TSubRect * FastGetSubRect( double x, double z ) { return FastGetSubRect( GetColFromX( x ), GetRowFromZ( z ) ); }; inline int GetRowFromZ(double z) { return (int)(z / fSubRectSize + fHalfTotalNumSubRects); }; inline int GetColFromX(double x) { return (int)(x / fSubRectSize + fHalfTotalNumSubRects); }; #ifdef EU07_USE_OLD_GROUNDCODE TEvent * FindEvent(const std::string &asEventName); void TrackJoin(TGroundNode *Current); private: // convert tp_terrain model to a series of triangle nodes void convert_terrain( TGroundNode const *Terrain ); void convert_terrain( TSubModel const *Submodel ); void RaTriangleDivider(TGroundNode *node); #endif public: #ifdef EU07_USE_OLD_GROUNDCODE void DynamicList( bool all = false ); void TrackBusyList(); void IsolatedBusyList(); void IsolatedBusy( const std::string t ); void RadioStop(vector3 pPosition); TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0, bool mech = false); TDynamicObject * CouplerNearest(vector3 pPosition, double distance = 20.0, bool mech = false); #endif void DynamicRemove(TDynamicObject *dyn); void TerrainRead(std::string const &f); void TerrainWrite(); #ifdef EU07_USE_OLD_GROUNDCODE void Silence(vector3 gdzie); #endif }; //---------------------------------------------------------------------------