16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 19:49:19 +02:00

continued refactoring: lines, terrain models; render culling optimizations and fixes

This commit is contained in:
tmj-fstate
2017-10-17 19:49:14 +02:00
parent 630b9ecf1b
commit 87348a2ab8
25 changed files with 1062 additions and 244 deletions

View File

@@ -232,9 +232,14 @@ void TAnimContainer::UpdateModel() {
fTranslateSpeed = 0.0; // wyłączenie przeliczania wektora fTranslateSpeed = 0.0; // wyłączenie przeliczania wektora
if (LengthSquared3(vTranslation) <= 0.0001) // jeśli jest w punkcie początkowym if (LengthSquared3(vTranslation) <= 0.0001) // jeśli jest w punkcie początkowym
iAnim &= ~2; // wyłączyć zmianę pozycji submodelu iAnim &= ~2; // wyłączyć zmianę pozycji submodelu
if (evDone) if( evDone ) {
Global::AddToQuery(evDone, NULL); // wykonanie eventu informującego o // wykonanie eventu informującego o zakończeniu
// zakończeniu #ifdef EU07_USE_OLD_GROUNDCODE
Global::AddToQuery( evDone, NULL );
#else
simulation::Events.AddToQuery( evDone, nullptr );
#endif
}
} }
} }
if (fRotateSpeed != 0.0) if (fRotateSpeed != 0.0)
@@ -299,9 +304,14 @@ void TAnimContainer::UpdateModel() {
if (!anim) if (!anim)
{ // nie potrzeba przeliczać już { // nie potrzeba przeliczać już
fRotateSpeed = 0.0; fRotateSpeed = 0.0;
if (evDone) if( evDone ) {
Global::AddToQuery(evDone, NULL); // wykonanie eventu informującego o // wykonanie eventu informującego o zakończeniu
// zakończeniu #ifdef EU07_USE_OLD_GROUNDCODE
Global::AddToQuery( evDone, NULL );
#else
simulation::Events.AddToQuery( evDone, nullptr );
#endif
}
} }
} }
if( fAngleSpeed != 0.f ) { if( fAngleSpeed != 0.f ) {
@@ -330,7 +340,11 @@ void TAnimContainer::PrepareModel()
fAngleSpeed = 0.0; // wyłączenie przeliczania wektora fAngleSpeed = 0.0; // wyłączenie przeliczania wektora
if( evDone ) { if( evDone ) {
// wykonanie eventu informującego o zakończeniu // wykonanie eventu informującego o zakończeniu
#ifdef EU07_USE_OLD_GROUNDCODE
Global::AddToQuery( evDone, NULL ); Global::AddToQuery( evDone, NULL );
#else
simulation::Events.AddToQuery( evDone, nullptr );
#endif
} }
} }
else else

View File

@@ -149,6 +149,10 @@ public:
material_data const * material_data const *
Material() const { Material() const {
return &m_materialdata; } return &m_materialdata; }
inline
TModel3d *
Model() {
return pModel; }
// members // members
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania

View File

@@ -18,9 +18,6 @@ http://mozilla.org/MPL/2.0/.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// TViewPyramid TCamera::OrgViewPyramid;
//={vector3(-1,1,1),vector3(1,1,1),vector3(-1,-1,1),vector3(1,-1,1),vector3(0,0,0)};
void TCamera::Init(vector3 NPos, vector3 NAngle) void TCamera::Init(vector3 NPos, vector3 NAngle)
{ {
@@ -37,8 +34,8 @@ void TCamera::Init(vector3 NPos, vector3 NAngle)
void TCamera::OnCursorMove(double x, double y) void TCamera::OnCursorMove(double x, double y)
{ {
// McZapkie-170402: zeby mysz dzialala zawsze if (Type==tp_Follow) // McZapkie-170402: zeby mysz dzialala zawsze if (Type==tp_Follow)
Pitch += y; Yaw -= x;
Yaw += -x; Pitch -= y;
if (Yaw > M_PI) if (Yaw > M_PI)
Yaw -= 2 * M_PI; Yaw -= 2 * M_PI;
else if (Yaw < -M_PI) else if (Yaw < -M_PI)
@@ -62,7 +59,7 @@ TCamera::OnCommand( command_data const &Command ) {
OnCursorMove( OnCursorMove(
reinterpret_cast<double const &>( Command.param1 ) * 0.005 * Global::fMouseXScale / Global::ZoomFactor, reinterpret_cast<double const &>( Command.param1 ) * 0.005 * Global::fMouseXScale / Global::ZoomFactor,
reinterpret_cast<double const &>( Command.param2 ) * -0.01 * Global::fMouseYScale / Global::ZoomFactor ); reinterpret_cast<double const &>( Command.param2 ) * 0.01 * Global::fMouseYScale / Global::ZoomFactor );
break; break;
} }

View File

@@ -5501,3 +5501,18 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
} }
} }
} }
// legacy method, sends list of vehicles over network
void
vehicle_table::DynamicList( bool const Onlycontrolled ) const {
// odesłanie nazw pojazdów dostępnych na scenerii (nazwy, szczególnie wagonów, mogą się powtarzać!)
for( auto const *vehicle : m_items ) {
if( ( false == Onlycontrolled )
|| ( vehicle->Mechanik != nullptr ) ) {
// same nazwy pojazdów
multiplayer::WyslijString( vehicle->asName, 6 );
}
}
// informacja o końcu listy
multiplayer::WyslijString( "none", 6 );
}

View File

@@ -495,6 +495,9 @@ public:
// legacy method, checks for presence and height of traction wire for specified vehicle // legacy method, checks for presence and height of traction wire for specified vehicle
void void
update_traction( TDynamicObject *Vehicle ); update_traction( TDynamicObject *Vehicle );
// legacy method, sends list of vehicles over network
void
DynamicList( bool const Onlycontrolled = false ) const;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -46,8 +46,7 @@ TEvent::~TEvent() {
switch (Type) switch (Type)
{ // sprzątanie { // sprzątanie
case tp_Multiple: case tp_Multiple:
// SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa obiektu powiązanego zamieniana na // SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa obiektu powiązanego zamieniana na wskaźnik
// wskaźnik
if (iFlags & conditional_memstring) // o ile jest łańcuch do porównania w memcompare if (iFlags & conditional_memstring) // o ile jest łańcuch do porównania w memcompare
SafeDeleteArray(Params[10].asText); SafeDeleteArray(Params[10].asText);
break; break;
@@ -82,8 +81,7 @@ void TEvent::Conditions(cParser *parser, std::string s)
if (!asNodeName.empty()) if (!asNodeName.empty())
{ // podczepienie łańcucha, jeśli nie jest pusty { // podczepienie łańcucha, jeśli nie jest pusty
// BUG: source of a memory leak -- the array never gets deleted. fix the destructor // BUG: source of a memory leak -- the array never gets deleted. fix the destructor
Params[9].asText = new char[asNodeName.size() + 1]; // usuwane i zamieniane na Params[9].asText = new char[asNodeName.size() + 1]; // usuwane i zamieniane na wskaźnik
// wskaźnik
strcpy(Params[9].asText, asNodeName.c_str()); strcpy(Params[9].asText, asNodeName.c_str());
} }
parser->getTokens(); parser->getTokens();
@@ -860,17 +858,17 @@ event_manager::AddToQuery( TEvent *Event, TDynamicObject *Owner ) {
} }
//if (DebugModeFlag) //if (DebugModeFlag)
WriteLog( WriteLog(
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command ( " "EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command - ["
+ std::string( Event->Params[ 0 ].asText ) + " " + std::string{ Event->Params[ 0 ].asText } + "] ["
+ std::to_string( Event->Params[ 1 ].asdouble ) + " " + to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
+ std::to_string( Event->Params[ 2 ].asdouble ) + " )" ); + to_string( Event->Params[ 2 ].asdouble, 2 ) + " ]" );
} }
//else if (DebugModeFlag) //else if (DebugModeFlag)
WriteLog( WriteLog(
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues ( " "EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues - ["
+ std::string( Event->Params[ 0 ].asText ) + " " + std::string( Event->Params[ 0 ].asText ) + "] ["
+ std::to_string( Event->Params[ 1 ].asdouble ) + " " + to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
+ std::to_string( Event->Params[ 2 ].asdouble ) + " )" ); + to_string( Event->Params[ 2 ].asdouble, 2 ) + "]" );
} }
// jeśli jest kolejny o takiej samej nazwie, to idzie do kolejki (and if there's no joint event it'll be set to null and processing will end here) // jeśli jest kolejny o takiej samej nazwie, to idzie do kolejki (and if there's no joint event it'll be set to null and processing will end here)
do { do {
@@ -975,13 +973,11 @@ event_manager::CheckQuery() {
break; break;
case tp_GetValues: { case tp_GetValues: {
if( m_workevent->Activator ) { if( m_workevent->Activator ) {
/*
// TODO: re-enable when messaging module is in place // TODO: re-enable when messaging module is in place
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
// potwierdzenie wykonania dla serwera (odczyt semafora już tak nie działa) // potwierdzenie wykonania dla serwera (odczyt semafora już tak nie działa)
WyslijEvent( tmpEvent->asName, tmpEvent->Activator->name() ); multiplayer::WyslijEvent( m_workevent->asName, m_workevent->Activator->name() );
} }
*/
m_workevent->Params[ 9 ].asMemCell->PutCommand( m_workevent->Params[ 9 ].asMemCell->PutCommand(
m_workevent->Activator->Mechanik, m_workevent->Activator->Mechanik,
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
@@ -1124,13 +1120,10 @@ event_manager::CheckQuery() {
m_workevent->Params[ 1 ].asdouble, m_workevent->Params[ 1 ].asdouble,
m_workevent->Params[ 2 ].asdouble ); m_workevent->Params[ 2 ].asdouble );
} }
/*
// TODO: re-enable when messaging module is in place
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
// dajemy znać do serwera o przełożeniu // dajemy znać do serwera o przełożeniu
WyslijEvent( m_workevent->asName, "" ); // wysłanie nazwy eventu przełączajacego multiplayer::WyslijEvent( m_workevent->asName, "" ); // wysłanie nazwy eventu przełączajacego
} }
*/
// Ra: bardziej by się przydała nazwa toru, ale nie ma do niej stąd dostępu // Ra: bardziej by się przydała nazwa toru, ale nie ma do niej stąd dostępu
break; break;
} }
@@ -1170,21 +1163,18 @@ event_manager::CheckQuery() {
} }
} }
} }
/*
// TODO: re-enable when messaging component is in place
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
// dajemy znać do serwera o wykonaniu // dajemy znać do serwera o wykonaniu
if( ( m_workevent->iFlags & conditional_anyelse ) == 0 ) { if( ( m_workevent->iFlags & conditional_anyelse ) == 0 ) {
// jednoznaczne tylko, gdy nie było else // jednoznaczne tylko, gdy nie było else
if( m_workevent->Activator ) { if( m_workevent->Activator ) {
WyslijEvent( m_workevent->asName, m_workevent->Activator->name() ); multiplayer::WyslijEvent( m_workevent->asName, m_workevent->Activator->name() );
} }
else { else {
WyslijEvent( m_workevent->asName, "" ); multiplayer::WyslijEvent( m_workevent->asName, "" );
} }
} }
} }
*/
} }
break; break;
} }
@@ -1273,8 +1263,8 @@ event_manager::CheckQuery() {
+ to_string( m_workevent->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" ); + to_string( m_workevent->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" );
} }
else { else {
// TODO: re-enable when cell manager is in place
/* /*
// TODO: re-enable when cell manager is in place
// lista wszystkich // lista wszystkich
for( TGroundNode *Current = nRootOfType[ TP_MEMCELL ]; Current; Current = Current->nNext ) { for( TGroundNode *Current = nRootOfType[ TP_MEMCELL ]; Current; Current = Current->nNext ) {
WriteLog( "Memcell \"" + Current->asName + "\": " WriteLog( "Memcell \"" + Current->asName + "\": "

View File

@@ -1001,13 +1001,12 @@ TDynamicObject *Global::DynamicNearest()
{ // ustalenie pojazdu najbliższego kamerze { // ustalenie pojazdu najbliższego kamerze
return pGround->DynamicNearest(pCamera->Pos); return pGround->DynamicNearest(pCamera->Pos);
}; };
#endif
TDynamicObject *Global::CouplerNearest() TDynamicObject *Global::CouplerNearest()
{ // ustalenie pojazdu najbliższego kamerze { // ustalenie pojazdu najbliższego kamerze
return pGround->CouplerNearest(pCamera->Pos); return pGround->CouplerNearest(pCamera->Pos);
}; };
#endif
bool Global::AddToQuery(TEvent *event, TDynamicObject *who) bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
{ {
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
@@ -1016,6 +1015,7 @@ bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
return simulation::Events.AddToQuery( event, who ); return simulation::Events.AddToQuery( event, who );
#endif #endif
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool Global::DoEvents() bool Global::DoEvents()

View File

@@ -299,8 +299,8 @@ class Global
static std::string GetNextSymbol(); static std::string GetNextSymbol();
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
static TDynamicObject * DynamicNearest(); static TDynamicObject * DynamicNearest();
#endif
static TDynamicObject * CouplerNearest(); static TDynamicObject * CouplerNearest();
#endif
static bool AddToQuery(TEvent *event, TDynamicObject *who); static bool AddToQuery(TEvent *event, TDynamicObject *who);
static bool DoEvents(); static bool DoEvents();
static std::string Bezogonkow(std::string str, bool _ = false); static std::string Bezogonkow(std::string str, bool _ = false);

View File

@@ -243,7 +243,9 @@ void TSubRect::NodeAdd(TGroundNode *Node)
break; break;
case TP_TRACK: // TODO: tory z cieniem (tunel, canyon) też dać bez łączenia? case TP_TRACK: // TODO: tory z cieniem (tunel, canyon) też dać bez łączenia?
++iTracks; // jeden tor więcej ++iTracks; // jeden tor więcej
#ifdef EU07_USE_OLD_GROUNDCODE
Node->pTrack->RaOwnerSet(this); // do którego sektora ma zgłaszać animację Node->pTrack->RaOwnerSet(this); // do którego sektora ma zgłaszać animację
#endif
// NOTE: track merge/sort temporarily disabled to simplify unification of render code // NOTE: track merge/sort temporarily disabled to simplify unification of render code
// TODO: refactor sorting as universal part of drawing process in the renderer // TODO: refactor sorting as universal part of drawing process in the renderer
Node->nNext3 = nRenderRect; Node->nNext3 = nRenderRect;
@@ -340,6 +342,7 @@ TTrack * TSubRect::FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude)
return NULL; return NULL;
}; };
#ifdef EU07_USE_OLD_GROUNDCODE
bool TSubRect::RaTrackAnimAdd(TTrack *t) bool TSubRect::RaTrackAnimAdd(TTrack *t)
{ // aktywacja animacji torów w VBO (zwrotnica, obrotnica) { // aktywacja animacji torów w VBO (zwrotnica, obrotnica)
if( false == m_geometrycreated ) { if( false == m_geometrycreated ) {
@@ -365,6 +368,7 @@ void TSubRect::RaAnimate( unsigned int const Framestamp ) {
m_framestamp = Framestamp; m_framestamp = Framestamp;
}; };
#endif
TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude) TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude)
{ // szukanie przęsła w sektorze, którego koniec jest najbliższy (*Point) { // szukanie przęsła w sektorze, którego koniec jest najbliższy (*Point)
@@ -604,7 +608,7 @@ TGroundNode * TGround::DynamicFind(std::string const &Name)
return Current; return Current;
return NULL; return NULL;
}; };
#endif
void void
TGround::DynamicList(bool all) TGround::DynamicList(bool all)
{ // odesłanie nazw pojazdów dostępnych na scenerii (nazwy, szczególnie wagonów, mogą się { // odesłanie nazw pojazdów dostępnych na scenerii (nazwy, szczególnie wagonów, mogą się
@@ -614,7 +618,7 @@ TGround::DynamicList(bool all)
multiplayer::WyslijString(Current->asName, 6); // same nazwy pojazdów multiplayer::WyslijString(Current->asName, 6); // same nazwy pojazdów
multiplayer::WyslijString("none", 6); // informacja o końcu listy multiplayer::WyslijString("none", 6); // informacja o końcu listy
}; };
#ifdef EU07_USE_OLD_GROUNDCODE
// wyszukiwanie obiektu o podanej nazwie i konkretnym typie // wyszukiwanie obiektu o podanej nazwie i konkretnym typie
TGroundNode * TGroundNode *
TGround::FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType) { TGround::FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType) {
@@ -648,7 +652,7 @@ TGround::GetRect( double x, double z ) {
return nullptr; return nullptr;
} }
}; };
#ifdef EU07_USE_OLD_GROUNDCODE
// convert tp_terrain model to a series of triangle nodes // convert tp_terrain model to a series of triangle nodes
void void
TGround::convert_terrain( TGroundNode const *Terrain ) { TGround::convert_terrain( TGroundNode const *Terrain ) {
@@ -683,7 +687,7 @@ TGround::convert_terrain( TSubModel const *Submodel ) {
delete groundnode; delete groundnode;
} }
} }
#endif
double fTrainSetVel = 0; double fTrainSetVel = 0;
double fTrainSetDir = 0; double fTrainSetDir = 0;
double fTrainSetDist = 0; // odległość składu od punktu 1 w stronę punktu 2 double fTrainSetDist = 0; // odległość składu od punktu 1 w stronę punktu 2
@@ -2766,7 +2770,7 @@ void TGround::InitTraction()
} }
delete[] nEnds; // nie potrzebne już delete[] nEnds; // nie potrzebne już
}; };
#endif
void TGround::TrackJoin(TGroundNode *Current) void TGround::TrackJoin(TGroundNode *Current)
{ // wyszukiwanie sąsiednich torów do podłączenia (wydzielone na użytek obrotnicy) { // wyszukiwanie sąsiednich torów do podłączenia (wydzielone na użytek obrotnicy)
TTrack *Track = Current->pTrack; TTrack *Track = Current->pTrack;
@@ -2774,11 +2778,7 @@ void TGround::TrackJoin(TGroundNode *Current)
int iConnection; int iConnection;
if (!Track->CurrentPrev()) if (!Track->CurrentPrev())
{ {
#ifdef EU07_USE_OLD_GROUNDCODE
tmp = FindTrack(Track->CurrentSegment()->FastGetPoint_0(), iConnection, Current); // Current do pominięcia tmp = FindTrack(Track->CurrentSegment()->FastGetPoint_0(), iConnection, Current); // Current do pominięcia
#else
std::tie( tmp, iConnection ) = simulation::Region->find_path( Track->CurrentSegment()->FastGetPoint_0(), Track );
#endif
switch (iConnection) switch (iConnection)
{ {
case 0: case 0:
@@ -2791,11 +2791,7 @@ void TGround::TrackJoin(TGroundNode *Current)
} }
if (!Track->CurrentNext()) if (!Track->CurrentNext())
{ {
#ifdef EU07_USE_OLD_GROUNDCODE
tmp = FindTrack(Track->CurrentSegment()->FastGetPoint_1(), iConnection, Current); tmp = FindTrack(Track->CurrentSegment()->FastGetPoint_1(), iConnection, Current);
#else
std::tie( tmp, iConnection ) = simulation::Region->find_path( Track->CurrentSegment()->FastGetPoint_1(), Track );
#endif
switch (iConnection) switch (iConnection)
{ {
case 0: case 0:
@@ -2807,7 +2803,7 @@ void TGround::TrackJoin(TGroundNode *Current)
} }
} }
} }
#ifdef EU07_USE_OLD_GROUNDCODE
// McZapkie-070602: wyzwalacze zdarzen // McZapkie-070602: wyzwalacze zdarzen
bool TGround::InitLaunchers() bool TGround::InitLaunchers()
{ {
@@ -3755,7 +3751,7 @@ bool TGround::GetTraction(TDynamicObject *model)
return true; return true;
}; };
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -3800,6 +3796,7 @@ TDynamicObject * TGround::DynamicNearest(vector3 pPosition, double distance, boo
} }
return dyn; return dyn;
}; };
TDynamicObject * TGround::CouplerNearest(vector3 pPosition, double distance, bool mech) TDynamicObject * TGround::CouplerNearest(vector3 pPosition, double distance, bool mech)
{ // wyszukanie pojazdu, którego sprzęg jest najbliżej względem (pPosition) { // wyszukanie pojazdu, którego sprzęg jest najbliżej względem (pPosition)
TGroundNode *node; TGroundNode *node;
@@ -3829,6 +3826,7 @@ TDynamicObject * TGround::CouplerNearest(vector3 pPosition, double distance, boo
} }
return dyn; return dyn;
}; };
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TGround::DynamicRemove(TDynamicObject *dyn) void TGround::DynamicRemove(TDynamicObject *dyn)
{ // Ra: usunięcie pojazdów ze scenerii (gdy dojadą na koniec i nie sa potrzebne) { // Ra: usunięcie pojazdów ze scenerii (gdy dojadą na koniec i nie sa potrzebne)
@@ -3951,7 +3949,7 @@ void TGround::TerrainWrite()
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#ifdef EU07_USE_OLD_GROUNDCODE
void TGround::TrackBusyList() void TGround::TrackBusyList()
{ // wysłanie informacji o wszystkich zajętych odcinkach { // wysłanie informacji o wszystkich zajętych odcinkach
TGroundNode *Current; TGroundNode *Current;
@@ -3987,6 +3985,7 @@ void TGround::IsolatedBusy(const std::string t)
} }
multiplayer::WyslijString(t, 10); // wolny multiplayer::WyslijString(t, 10); // wolny
}; };
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TGround::Silence(vector3 gdzie) void TGround::Silence(vector3 gdzie)

View File

@@ -128,14 +128,8 @@ public:
void InitNormals(); void InitNormals();
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
}; };
/*
struct bounding_area {
glm::vec3 center; // mid point of the rectangle class TSubRect : public CMesh
float radius { 0.0f }; // radius of the bounding sphere
};
*/
class TSubRect : /*public Resource,*/ public CMesh
{ // sektor składowy kwadratu kilometrowego { // sektor składowy kwadratu kilometrowego
public: public:
scene::bounding_area m_area; scene::bounding_area m_area;
@@ -165,8 +159,10 @@ class TSubRect : /*public Resource,*/ public CMesh
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur) void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude); TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *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 bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji torów void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji torów
#endif
void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów
}; };
@@ -273,9 +269,6 @@ class TGround
bool CheckQuery(); bool CheckQuery();
TGroundNode * DynamicFindAny(std::string const &Name); TGroundNode * DynamicFindAny(std::string const &Name);
TGroundNode * DynamicFind(std::string const &Name); TGroundNode * DynamicFind(std::string const &Name);
#endif
void DynamicList(bool all = false);
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode * FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType); TGroundNode * FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType);
#endif #endif
TGroundRect * GetRect( double x, double z ); TGroundRect * GetRect( double x, double z );
@@ -295,25 +288,23 @@ class TGround
return (int)(x / fSubRectSize + fHalfTotalNumSubRects); }; return (int)(x / fSubRectSize + fHalfTotalNumSubRects); };
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
TEvent * FindEvent(const std::string &asEventName); TEvent * FindEvent(const std::string &asEventName);
#endif
void TrackJoin(TGroundNode *Current); void TrackJoin(TGroundNode *Current);
private: private:
// convert tp_terrain model to a series of triangle nodes // convert tp_terrain model to a series of triangle nodes
void convert_terrain( TGroundNode const *Terrain ); void convert_terrain( TGroundNode const *Terrain );
void convert_terrain( TSubModel const *Submodel ); void convert_terrain( TSubModel const *Submodel );
#ifdef EU07_USE_OLD_GROUNDCODE
void RaTriangleDivider(TGroundNode *node); void RaTriangleDivider(TGroundNode *node);
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
#endif #endif
public: public:
#ifdef EU07_USE_OLD_GROUNDCODE
void DynamicList( bool all = false );
void TrackBusyList(); void TrackBusyList();
void IsolatedBusyList(); void IsolatedBusyList();
void IsolatedBusy( const std::string t ); void IsolatedBusy( const std::string t );
void RadioStop(vector3 pPosition); void RadioStop(vector3 pPosition);
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0, bool mech = false); TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
TDynamicObject * CouplerNearest(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 DynamicRemove(TDynamicObject *dyn);
void TerrainRead(std::string const &f); void TerrainRead(std::string const &f);
void TerrainWrite(); void TerrainWrite();

View File

@@ -176,8 +176,14 @@ void TMemCell::StopCommandSent()
if (!bCommand) if (!bCommand)
return; return;
bCommand = false; bCommand = false;
if (OnSent) // jeśli jest event if( OnSent ) {
// jeśli jest event
#ifdef EU07_USE_OLD_GROUNDCODE
Global::AddToQuery( OnSent, NULL ); Global::AddToQuery( OnSent, NULL );
#else
simulation::Events.AddToQuery( OnSent, nullptr );
#endif
}
}; };
void TMemCell::AssignEvents(TEvent *e) void TMemCell::AssignEvents(TEvent *e)

View File

@@ -19,7 +19,9 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
#include "logs.h" #include "logs.h"
#include "mczapkie/mctools.h" #include "mczapkie/mctools.h"
#include "Usefull.h" #include "Usefull.h"
#ifdef EU07_USE_OLD_GROUNDCODE
#include "ground.h" #include "ground.h"
#endif
#include "renderer.h" #include "renderer.h"
#include "Timer.h" #include "Timer.h"
#include "mtable.h" #include "mtable.h"
@@ -988,11 +990,11 @@ TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &
// data offset is used to determine data offset of each submodel into single shared geometry bank // data offset is used to determine data offset of each submodel into single shared geometry bank
// (the offsets are part of legacy system which we now need to work around for backward compatibility) // (the offsets are part of legacy system which we now need to work around for backward compatibility)
if( Child ) if( Child )
Child->create_geometry( Dataoffset, Bank ); Child->create_geometry( Dataoffset, Bank );
if( false == Vertices.empty() ) { if( false == Vertices.empty() ) {
tVboPtr = static_cast<int>( Dataoffset ); tVboPtr = static_cast<int>( Dataoffset );
Dataoffset += Vertices.size(); Dataoffset += Vertices.size();
// conveniently all relevant custom node types use GL_POINTS, or we'd have to determine the type on individual basis // conveniently all relevant custom node types use GL_POINTS, or we'd have to determine the type on individual basis
@@ -1003,10 +1005,29 @@ TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &
m_geometry = GfxRenderer.Insert( Vertices, Bank, type ); m_geometry = GfxRenderer.Insert( Vertices, Bank, type );
} }
if( m_geometry != NULL ) {
// calculate bounding radius while we're at it
// NOTE: doesn't take into account transformation hierarchy TODO: implement it
float squaredradius{ 0.f };
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
squaredradius = static_cast<float>( glm::length2( vertex.position ) );
if( squaredradius > m_boundingradius ) {
m_boundingradius = squaredradius;
}
}
if( m_boundingradius > 0.f ) { m_boundingradius = std::sqrt( m_boundingradius ); }
if( Parent ) {
// propagate radius up the chain
Parent->m_boundingradius = std::max(
Parent->m_boundingradius,
m_boundingradius );
}
}
if( Next ) if( Next )
Next->create_geometry( Dataoffset, Bank ); Next->create_geometry( Dataoffset, Bank );
} }
#ifdef EU07_USE_OLD_GROUNDCODE
// places contained geometry in provided ground node // places contained geometry in provided ground node
void void
TSubModel::convert( TGroundNode &Groundnode ) const { TSubModel::convert( TGroundNode &Groundnode ) const {
@@ -1063,7 +1084,7 @@ TSubModel::convert( TGroundNode &Groundnode ) const {
Groundnode.fSquareRadius += squareradius; Groundnode.fSquareRadius += squareradius;
} }
} }
#endif
void TSubModel::ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular ) void TSubModel::ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular )
{ // ustawienie kolorów dla modelu terenu { // ustawienie kolorów dla modelu terenu
f4Ambient = glm::vec4( Ambient, 1.0f ); f4Ambient = glm::vec4( Ambient, 1.0f );
@@ -1759,18 +1780,11 @@ void TModel3d::Init()
return; // operacje zostały już wykonane return; // operacje zostały już wykonane
if (Root) if (Root)
{ {
if (iFlags & 0x0200) // jeśli wczytano z pliku tekstowego if (iFlags & 0x0200) {
{ // jest jakiś dziwny błąd, że obkręcany ma być tylko ostatni submodel // jeśli wczytano z pliku tekstowego jest jakiś dziwny błąd,
// głównego łańcucha // że obkręcany ma być tylko ostatni submodel głównego łańcucha
// TSubModel *p=Root; // argumet określa, czy wykonać pierwotny obrót
// do Root->InitialRotate(true);
//{p->InitialRotate(true); //ostatniemu należy się konwersja układu
// współrzędnych
// p=p->NextGet();
//}
// while (p->NextGet())
// Root->InitialRotate(false); //a poprzednim tylko optymalizacja
Root->InitialRotate(true); // argumet określa, czy wykonać pierwotny obrót
} }
iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu
if (iNumVerts) { if (iNumVerts) {
@@ -1788,11 +1802,6 @@ void TModel3d::Init()
} }
}; };
void TModel3d::BreakHierarhy()
{
Error("Not implemented yet :(");
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 2012-02 funkcje do tworzenia terenu z E3D // 2012-02 funkcje do tworzenia terenu z E3D
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -50,7 +50,12 @@ enum TAnimType // rodzaj animacji
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
}; };
#ifdef EU07_USE_OLD_GROUNDCODE
class TGroundNode; class TGroundNode;
#endif
namespace scene {
class shape_node;
}
class TSubModel class TSubModel
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów { // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
@@ -59,6 +64,7 @@ class TSubModel
friend class opengl_renderer; friend class opengl_renderer;
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
friend class TDynamicObject; // temporary etc friend class TDynamicObject; // temporary etc
friend class scene::shape_node; // temporary etc
public: public:
enum normalization { enum normalization {
@@ -131,10 +137,8 @@ private:
public: // chwilowo public: // chwilowo
float3 v_TransVector { 0.0f, 0.0f, 0.0f }; float3 v_TransVector { 0.0f, 0.0f, 0.0f };
/*
basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
*/
vertex_array Vertices; vertex_array Vertices;
float m_boundingradius { 0 };
size_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację size_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację
TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane
public: public:
@@ -163,9 +167,6 @@ public:
TSubModel * NextGet() { return Next; }; TSubModel * NextGet() { return Next; };
TSubModel * ChildGet() { return Child; }; TSubModel * ChildGet() { return Child; };
int TriangleAdd(TModel3d *m, material_handle tex, int tri); int TriangleAdd(TModel3d *m, material_handle tex, int tri);
/*
basic_vertex * TrianglePtr(int tex, int pos, glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
*/
void SetRotate(float3 vNewRotateAxis, float fNewAngle); void SetRotate(float3 vNewRotateAxis, float fNewAngle);
void SetRotateXYZ(vector3 vNewAngles); void SetRotateXYZ(vector3 vNewAngles);
void SetRotateXYZ(float3 vNewAngles); void SetRotateXYZ(float3 vNewAngles);
@@ -215,8 +216,9 @@ public:
std::vector<float4x4>&); std::vector<float4x4>&);
void serialize_geometry( std::ostream &Output ) const; void serialize_geometry( std::ostream &Output ) const;
// places contained geometry in provided ground node // places contained geometry in provided ground node
#ifdef EU07_USE_OLD_GROUNDCODE
void convert( TGroundNode &Groundnode ) const; void convert( TGroundNode &Groundnode ) const;
#endif
}; };
class TModel3d : public CMesh class TModel3d : public CMesh
@@ -236,6 +238,11 @@ private:
std::string asBinary; // nazwa pod którą zapisać model binarny std::string asBinary; // nazwa pod którą zapisać model binarny
std::string m_filename; std::string m_filename;
public: public:
float bounding_radius() const {
return (
Root ?
Root->m_boundingradius :
0.f ); }
inline TSubModel * GetSMRoot() { return (Root); }; inline TSubModel * GetSMRoot() { return (Root); };
TModel3d(); TModel3d();
~TModel3d(); ~TModel3d();
@@ -246,7 +253,6 @@ public:
void LoadFromBinFile(std::string const &FileName, bool dynamic); void LoadFromBinFile(std::string const &FileName, bool dynamic);
bool LoadFromFile(std::string const &FileName, bool dynamic); bool LoadFromFile(std::string const &FileName, bool dynamic);
void SaveToBinFile(std::string const &FileName); void SaveToBinFile(std::string const &FileName);
void BreakHierarhy();
int Flags() const { return iFlags; }; int Flags() const { return iFlags; };
void Init(); void Init();
std::string NameGet() { return m_filename; }; std::string NameGet() { return m_filename; };

View File

@@ -84,16 +84,14 @@ TIsolated::TIsolated(std::string const &n, TIsolated *i) :
// utworznie obwodu izolowanego. nothing to do here. // utworznie obwodu izolowanego. nothing to do here.
}; };
// TODO: put this in the cleanup routine on exit void TIsolated::DeleteAll() {
/*
TIsolated *p=pRoot; while( pRoot ) {
while (pRoot) auto *next = pRoot->Next();
{ delete pRoot;
p=pRoot; pRoot = next;
p->pNext=NULL; }
delete p;
} }
*/
TIsolated * TIsolated::Find(std::string const &n) TIsolated * TIsolated::Find(std::string const &n)
{ // znalezienie obiektu albo utworzenie nowego { // znalezienie obiektu albo utworzenie nowego
@@ -1065,7 +1063,11 @@ bool TTrack::InMovement()
return false; return false;
}; };
#ifdef EU07_USE_OLD_GROUNDCODE
void TTrack::RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined) void TTrack::RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined)
#else
void TTrack::RaAssign( scene::basic_cell *gn, TAnimModel *am, TEvent *done, TEvent *joined )
#endif
{ // Ra: wiązanie toru z modelem obrotnicy { // Ra: wiązanie toru z modelem obrotnicy
if (eType == tt_Table) if (eType == tt_Table)
{ {
@@ -2259,7 +2261,7 @@ bool TTrack::Switch(int i, float const t, float const d)
} }
else if (eType == tt_Table) else if (eType == tt_Table)
{ // blokowanie (0, szukanie torów) lub odblokowanie (1, rozłączenie) obrotnicy { // blokowanie (0, szukanie torów) lub odblokowanie (1, rozłączenie) obrotnicy
if (i) if (i) // NOTE: this condition seems opposite to intention/comment? TODO: investigate this
{ // 0: rozłączenie sąsiednich torów od obrotnicy { // 0: rozłączenie sąsiednich torów od obrotnicy
if (trPrev) // jeśli jest tor od Point1 obrotnicy if (trPrev) // jeśli jest tor od Point1 obrotnicy
if (iPrevDirection) // 0:dołączony Point1, 1:dołączony Point2 if (iPrevDirection) // 0:dołączony Point1, 1:dołączony Point2
@@ -2276,25 +2278,34 @@ bool TTrack::Switch(int i, float const t, float const d)
fVelocity = 0.0; // AI, nie ruszaj się! fVelocity = 0.0; // AI, nie ruszaj się!
if (SwitchExtension->pOwner) if (SwitchExtension->pOwner)
SwitchExtension->pOwner->RaTrackAnimAdd(this); // dodanie do listy animacyjnej SwitchExtension->pOwner->RaTrackAnimAdd(this); // dodanie do listy animacyjnej
// TODO: unregister path ends in the owner cell
} }
else else
{ // 1: ustalenie finalnego położenia (gdy nie było animacji) { // 1: ustalenie finalnego położenia (gdy nie było animacji)
RaAnimate(); // ostatni etap animowania RaAnimate(); // ostatni etap animowania
// zablokowanie pozycji i połączenie do sąsiednich torów // zablokowanie pozycji i połączenie do sąsiednich torów
// TODO: register new position of the path endpoints with the region
#ifdef EU07_USE_OLD_GROUNDCODE
Global::pGround->TrackJoin(SwitchExtension->pMyNode); Global::pGround->TrackJoin(SwitchExtension->pMyNode);
#else
simulation::Region->TrackJoin( this );
#endif
if (trNext || trPrev) if (trNext || trPrev)
{ {
fVelocity = 6.0; // jazda dozwolona fVelocity = 6.0; // jazda dozwolona
if (trPrev) if( ( trPrev )
if (trPrev->fVelocity == && ( trPrev->fVelocity == 0.0 ) ) {
0.0) // ustawienie 0 da możliwość zatrzymania AI na obrotnicy // ustawienie 0 da możliwość zatrzymania AI na obrotnicy
trPrev->VelocitySet( 6.0 ); // odblokowanie dołączonego toru do jazdy trPrev->VelocitySet( 6.0 ); // odblokowanie dołączonego toru do jazdy
if (trNext) }
if (trNext->fVelocity == 0.0) if( ( trNext )
&& ( trNext->fVelocity == 0.0 ) ) {
trNext->VelocitySet( 6.0 ); trNext->VelocitySet( 6.0 );
if (SwitchExtension->evPlus) // w starych sceneriach może nie być }
Global::AddToQuery(SwitchExtension->evPlus, if( SwitchExtension->evPlus ) { // w starych sceneriach może nie być
NULL); // potwierdzenie wykonania (np. odpala WZ) // potwierdzenie wykonania (np. odpala WZ)
Global::AddToQuery( SwitchExtension->evPlus, nullptr );
}
} }
} }
SwitchExtension->CurrentIndex = i; // zapamiętanie stanu zablokowania SwitchExtension->CurrentIndex = i; // zapamiętanie stanu zablokowania
@@ -2528,7 +2539,11 @@ TTrack * TTrack::RaAnimate()
cosa = -hlen * std::cos(glm::radians(SwitchExtension->fOffset)); cosa = -hlen * std::cos(glm::radians(SwitchExtension->fOffset));
SwitchExtension->vTrans = ac->TransGet(); SwitchExtension->vTrans = ac->TransGet();
vector3 middle = vector3 middle =
#ifdef EU07_USE_OLD_GROUNDCODE
SwitchExtension->pMyNode->pCenter + SwitchExtension->pMyNode->pCenter +
#else
SwitchExtension->pMyNode->area().center +
#endif
SwitchExtension->vTrans; // SwitchExtension->Segments[0]->FastGetPoint(0.5); SwitchExtension->vTrans; // SwitchExtension->Segments[0]->FastGetPoint(0.5);
Segment->Init(middle + vector3(sina, 0.0, cosa), Segment->Init(middle + vector3(sina, 0.0, cosa),
middle - vector3(sina, 0.0, cosa), 5.0); // nowy odcinek middle - vector3(sina, 0.0, cosa), 5.0); // nowy odcinek
@@ -2774,6 +2789,11 @@ TTrack * TTrack::Connected(int s, double &d) const
path_table::~path_table() {
TIsolated::DeleteAll();
}
// legacy method, initializes tracks after deserialization from scenario file // legacy method, initializes tracks after deserialization from scenario file
void void
path_table::InitTracks() { path_table::InitTracks() {
@@ -2957,3 +2977,46 @@ path_table::InitTracks() {
isolated = isolated->Next(); isolated = isolated->Next();
} }
} }
// legacy method, sends list of occupied paths over network
void
path_table::TrackBusyList() const {
// wysłanie informacji o wszystkich zajętych odcinkach
for( auto const *path : m_items ) {
if( ( false == path->name().empty() ) // musi być nazwa
&& ( false == path->Dynamics.empty() ) ) {
// zajęty
multiplayer::WyslijString( path->name(), 8 );
}
}
}
// legacy method, sends list of occupied path sections over network
void
path_table::IsolatedBusyList() const {
// wysłanie informacji o wszystkich odcinkach izolowanych
TIsolated *Current;
for( Current = TIsolated::Root(); Current; Current = Current->Next() ) {
if( Current->Busy() ) { multiplayer::WyslijString( Current->asName, 11 ); }
else { multiplayer::WyslijString( Current->asName, 10 ); }
}
multiplayer::WyslijString( "none", 10 ); // informacja o końcu listy
}
// legacy method, sends state of specified path section over network
void
path_table::IsolatedBusy( std::string const &Name ) const {
// wysłanie informacji o odcinku izolowanym (t)
// Ra 2014-06: do wyszukania użyć drzewka nazw
TIsolated *Current;
for( Current = TIsolated::Root(); Current; Current = Current->Next() ) {
if( Current->asName == Name ) {
if( Current->Busy() ) { multiplayer::WyslijString( Current->asName, 11 ); }
else { multiplayer::WyslijString( Current->asName, 10 ); }
// nie sprawdzaj dalszych
return;
}
}
multiplayer::WyslijString( Name, 10 ); // wolny (technically not found but, eh)
}

34
Track.h
View File

@@ -13,11 +13,15 @@ http://mozilla.org/MPL/2.0/.
#include <vector> #include <vector>
#include <deque> #include <deque>
#include "scenenode.h"
#include "Segment.h" #include "Segment.h"
#include "material.h" #include "material.h"
#include "scenenode.h"
#include "names.h" #include "names.h"
namespace scene {
class basic_cell;
}
enum TTrackType { enum TTrackType {
tt_Unknown, tt_Unknown,
tt_Normal, tt_Normal,
@@ -71,7 +75,11 @@ class TSwitchExtension
}; };
struct struct
{ // zmienne potrzebne tylko dla obrotnicy/przesuwnicy { // zmienne potrzebne tylko dla obrotnicy/przesuwnicy
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode *pMyNode; // dla obrotnicy do wtórnego podłączania torów TGroundNode *pMyNode; // dla obrotnicy do wtórnego podłączania torów
#else
scene::basic_cell *pMyNode; // TODO: convert this to observer pattern
#endif
// TAnimContainer *pAnim; //animator modelu dla obrotnicy // TAnimContainer *pAnim; //animator modelu dla obrotnicy
TAnimModel *pModel; // na razie model TAnimModel *pModel; // na razie model
}; };
@@ -83,7 +91,11 @@ class TSwitchExtension
}; };
}; };
bool bMovement = false; // czy w trakcie animacji bool bMovement = false; // czy w trakcie animacji
#ifdef EU07_USE_OLD_GROUNDCODE
TSubRect *pOwner = nullptr; // sektor, któremu trzeba zgłosić animację TSubRect *pOwner = nullptr; // sektor, któremu trzeba zgłosić animację
#else
scene::basic_cell *pOwner = nullptr; // TODO: convert this to observer pattern
#endif
TTrack *pNextAnim = nullptr; // następny tor do animowania TTrack *pNextAnim = nullptr; // następny tor do animowania
TEvent *evPlus = nullptr, TEvent *evPlus = nullptr,
*evMinus = nullptr; // zdarzenia sygnalizacji rozprucia *evMinus = nullptr; // zdarzenia sygnalizacji rozprucia
@@ -103,6 +115,7 @@ class TIsolated
TMemCell *pMemCell = nullptr; // automatyczna komórka pamięci, która współpracuje z odcinkiem izolowanym TMemCell *pMemCell = nullptr; // automatyczna komórka pamięci, która współpracuje z odcinkiem izolowanym
TIsolated(); TIsolated();
TIsolated(const std::string &n, TIsolated *i); TIsolated(const std::string &n, TIsolated *i);
static void DeleteAll();
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
bool Busy() { bool Busy() {
@@ -245,11 +258,20 @@ public:
#endif #endif
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
#ifdef EU07_USE_OLD_GROUNDCODE
void RaOwnerSet(TSubRect *o) { void RaOwnerSet(TSubRect *o) {
if (SwitchExtension) if (SwitchExtension)
SwitchExtension->pOwner = o; }; SwitchExtension->pOwner = o; };
#else
void RaOwnerSet( scene::basic_cell *o ) {
if( SwitchExtension ) { SwitchExtension->pOwner = o; } };
#endif
bool InMovement(); // czy w trakcie animacji? bool InMovement(); // czy w trakcie animacji?
#ifdef EU07_USE_OLD_GROUNDCODE
void RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined); void RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined);
#else
void RaAssign( scene::basic_cell *gn, TAnimModel *am, TEvent *done, TEvent *joined );
#endif
void RaAnimListAdd(TTrack *t); void RaAnimListAdd(TTrack *t);
TTrack * RaAnimate(); TTrack * RaAnimate();
@@ -278,9 +300,19 @@ public:
class path_table : public basic_table<TTrack> { class path_table : public basic_table<TTrack> {
public: public:
~path_table();
// legacy method, initializes tracks after deserialization from scenario file // legacy method, initializes tracks after deserialization from scenario file
void void
InitTracks(); InitTracks();
// legacy method, sends list of occupied paths over network
void
TrackBusyList() const;
// legacy method, sends list of occupied path sections over network
void
IsolatedBusyList() const;
// legacy method, sends state of specified path section over network
void
IsolatedBusy( std::string const &Name ) const;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -318,6 +318,8 @@ bool TWorld::Init( GLFWwindow *Window ) {
Controlled = NULL; Controlled = NULL;
mvControlled = NULL; mvControlled = NULL;
Camera.Type = tp_Free; Camera.Type = tp_Free;
DebugCamera = Camera;
Global::DebugCameraPosition = DebugCamera.Pos;
} }
// if (!Global::bMultiplayer) //na razie włączone // if (!Global::bMultiplayer) //na razie włączone
@@ -543,7 +545,7 @@ void TWorld::OnKeyDown(int cKey)
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
TDynamicObject *tmp = Ground.DynamicNearest( Camera.Pos, 50, true ); //łapiemy z obsadą TDynamicObject *tmp = Ground.DynamicNearest( Camera.Pos, 50, true ); //łapiemy z obsadą
#else #else
TDynamicObject *tmp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 50, true ) ); TDynamicObject *tmp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 50, true, false ) );
#endif #endif
if( ( tmp != nullptr ) if( ( tmp != nullptr )
&& ( tmp != Controlled ) ) { && ( tmp != Controlled ) ) {
@@ -689,7 +691,11 @@ void TWorld::OnKeyDown(int cKey)
else if( ( cKey == GLFW_KEY_PAUSE ) && ( Global::ctrlState ) && ( Global::shiftState ) ) { else if( ( cKey == GLFW_KEY_PAUSE ) && ( Global::ctrlState ) && ( Global::shiftState ) ) {
//[Ctrl]+[Break] hamowanie wszystkich pojazdów w okolicy // added shift to prevent odd issue with glfw producing pause presses on its own //[Ctrl]+[Break] hamowanie wszystkich pojazdów w okolicy // added shift to prevent odd issue with glfw producing pause presses on its own
if( Controlled->MoverParameters->Radio ) if( Controlled->MoverParameters->Radio )
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.RadioStop( Camera.Pos ); Ground.RadioStop( Camera.Pos );
#else
simulation::Region->RadioStop( Camera.Pos );
#endif
} }
else if (!Global::iPause) //||(cKey==VK_F4)) //podczas pauzy sterownaie nie działa, F4 tak else if (!Global::iPause) //||(cKey==VK_F4)) //podczas pauzy sterownaie nie działa, F4 tak
if (Train) if (Train)
@@ -725,7 +731,7 @@ void TWorld::OnKeyDown(int cKey)
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
TDynamicObject *temp = Global::DynamicNearest(); TDynamicObject *temp = Global::DynamicNearest();
#else #else
TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false ) ); TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false, false ) );
#endif #endif
if (temp) if (temp)
{ {
@@ -739,7 +745,11 @@ void TWorld::OnKeyDown(int cKey)
} }
else if (cKey == Global::Keys[k_EndSign]) else if (cKey == Global::Keys[k_EndSign])
{ // Ra 2014-07: zabrane z kabiny { // Ra 2014-07: zabrane z kabiny
#ifdef EU07_USE_OLD_GROUNDCODE
TDynamicObject *tmp = Global::CouplerNearest(); // domyślnie wyszukuje do 20m TDynamicObject *tmp = Global::CouplerNearest(); // domyślnie wyszukuje do 20m
#else
TDynamicObject *tmp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false, true ) );
#endif
if (tmp) if (tmp)
{ {
int CouplNr = (LengthSquared3(tmp->HeadPosition() - Camera.Pos) > int CouplNr = (LengthSquared3(tmp->HeadPosition() - Camera.Pos) >
@@ -772,7 +782,7 @@ void TWorld::OnKeyDown(int cKey)
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
TDynamicObject *temp = Global::DynamicNearest(); TDynamicObject *temp = Global::DynamicNearest();
#else #else
TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false ) ); TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false, false ) );
#endif #endif
if (temp) if (temp)
{ {
@@ -795,7 +805,7 @@ void TWorld::OnKeyDown(int cKey)
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
TDynamicObject *temp = Global::DynamicNearest(); TDynamicObject *temp = Global::DynamicNearest();
#else #else
TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false ) ); TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false, false ) );
#endif #endif
if (temp) if (temp)
{ {
@@ -835,6 +845,8 @@ void TWorld::InOutKey( bool const Near )
Train->Dynamic()->bDisplayCab = false; Train->Dynamic()->bDisplayCab = false;
DistantView( Near ); DistantView( Near );
} }
DebugCamera = Camera;
Global::DebugCameraPosition = DebugCamera.Pos;
} }
else else
{ // jazda w kabinie { // jazda w kabinie
@@ -1172,9 +1184,9 @@ TWorld::Update_Camera( double const Deltatime ) {
if( !d ) if( !d )
d = Ground.DynamicNearest( Camera.Pos, 1000 ); // dalej szukanie, jesli bliżej nie ma d = Ground.DynamicNearest( Camera.Pos, 1000 ); // dalej szukanie, jesli bliżej nie ma
#else #else
TDynamicObject *d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 300, false ) ); TDynamicObject *d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 300, false, false ) );
if( !d ) if( !d )
d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 1000, false ) ); // dalej szukanie, jesli bliżej nie ma d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 1000, false, false ) ); // dalej szukanie, jesli bliżej nie ma
#endif #endif
if( d && pDynamicNearest ) { if( d && pDynamicNearest ) {
// jeśli jakiś jest znaleziony wcześniej // jeśli jakiś jest znaleziony wcześniej
@@ -1361,7 +1373,7 @@ TWorld::Update_UI() {
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
Ground.DynamicNearest( Camera.Pos ) : Ground.DynamicNearest( Camera.Pos ) :
#else #else
std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false ) ) : std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false, false ) ) :
#endif #endif
Controlled ); // w trybie latania lokalizujemy wg mapy Controlled ); // w trybie latania lokalizujemy wg mapy
@@ -1446,7 +1458,7 @@ TWorld::Update_UI() {
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
Ground.DynamicNearest( Camera.Pos ) : Ground.DynamicNearest( Camera.Pos ) :
#else #else
std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false ) ) : std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false, false ) ) :
#endif #endif
Controlled ); // w trybie latania lokalizujemy wg mapy Controlled ); // w trybie latania lokalizujemy wg mapy
@@ -1714,7 +1726,7 @@ TWorld::Update_UI() {
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
Ground.DynamicNearest( Camera.Pos ) : Ground.DynamicNearest( Camera.Pos ) :
#else #else
std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false ) ) : std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false, false ) ) :
#endif #endif
Controlled ); // w trybie latania lokalizujemy wg mapy Controlled ); // w trybie latania lokalizujemy wg mapy
if( tmp == nullptr ) { if( tmp == nullptr ) {
@@ -1908,7 +1920,6 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) + " rcvd" ); std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) + " rcvd" );
#ifdef EU07_USE_OLD_GROUNDCODE #ifdef EU07_USE_OLD_GROUNDCODE
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
TEvent *e = Ground.FindEvent( TEvent *e = Ground.FindEvent(
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) ); std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
if( e ) if( e )
@@ -1918,7 +1929,6 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
} }
#else #else
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
auto *event = simulation::Events.FindEvent( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) ); auto *event = simulation::Events.FindEvent( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
if( event != nullptr ) { if( event != nullptr ) {
if( ( event->Type == tp_Multiple ) if( ( event->Type == tp_Multiple )
@@ -2027,7 +2037,6 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
if (t) if (t)
multiplayer::WyslijNamiary(t); // wysłanie informacji o pojeździe multiplayer::WyslijNamiary(t); // wysłanie informacji o pojeździe
#else #else
/*
// TODO: re-enable when messaging component is in place // TODO: re-enable when messaging component is in place
auto *vehicle = ( auto *vehicle = (
pRozkaz->cString[ 1 ] == '*' ? pRozkaz->cString[ 1 ] == '*' ?
@@ -2036,27 +2045,42 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
if( vehicle != nullptr ) { if( vehicle != nullptr ) {
multiplayer::WyslijNamiary( vehicle ); // wysłanie informacji o pojeździe multiplayer::WyslijNamiary( vehicle ); // wysłanie informacji o pojeździe
} }
*/
#endif #endif
} }
else { else {
// dla pustego wysyłamy ramki 6 z nazwami pojazdów AI (jeśli potrzebne wszystkie, to rozpoznać np. "*") // dla pustego wysyłamy ramki 6 z nazwami pojazdów AI (jeśli potrzebne wszystkie, to rozpoznać np. "*")
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.DynamicList(); Ground.DynamicList();
#else
simulation::Vehicles.DynamicList();
#endif
} }
} }
break; break;
case 8: // ponowne wysłanie informacji o zajętych odcinkach toru case 8: // ponowne wysłanie informacji o zajętych odcinkach toru
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy track" + " rcvd"); CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy track" + " rcvd");
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.TrackBusyList(); Ground.TrackBusyList();
#else
simulation::Paths.TrackBusyList();
#endif
break; break;
case 9: // ponowne wysłanie informacji o zajętych odcinkach izolowanych case 9: // ponowne wysłanie informacji o zajętych odcinkach izolowanych
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy isolated" + " rcvd"); CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy isolated" + " rcvd");
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.IsolatedBusyList(); Ground.IsolatedBusyList();
#else
simulation::Paths.IsolatedBusyList();
#endif
break; break;
case 10: // badanie zajętości jednego odcinka izolowanego case 10: // badanie zajętości jednego odcinka izolowanego
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " + CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) + " rcvd"); std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) + " rcvd");
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.IsolatedBusy(std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0]))); Ground.IsolatedBusy(std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])));
#else
simulation::Paths.IsolatedBusy( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
#endif
break; break;
case 11: // ustawienie parametrów ruchu pojazdu case 11: // ustawienie parametrów ruchu pojazdu
// Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0]))); // Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0])));
@@ -2096,7 +2120,25 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
} }
} }
#else #else
// TODO: implement if( pRozkaz->cString[ 1 ] ) // jeśli długość nazwy jest niezerowa
{ // szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #13
auto *lookup = (
pRozkaz->cString[ 2 ] == '*' ?
simulation::Vehicles.find( Global::asHumanCtrlVehicle ) : // nazwa pojazdu użytkownika
simulation::Vehicles.find( std::string( pRozkaz->cString + 2, (unsigned)pRozkaz->cString[ 1 ] ) ) ); // nazwa pojazdu
if( lookup == nullptr ) { break; } // nothing found, nothing to do
auto *d { lookup };
while( d != nullptr ) {
d->Damage( pRozkaz->cString[ 0 ] );
d = d->Next(); // pozostałe też
}
d = lookup->Prev();
while( d != nullptr ) {
d->Damage( pRozkaz->cString[ 0 ] );
d = d->Prev(); // w drugą stronę też
}
multiplayer::WyslijUszkodzenia( lookup->asName, lookup->MoverParameters->EngDmgFlag ); // zwrot informacji o pojeździe
}
#endif #endif
break; break;
} }

View File

@@ -93,6 +93,7 @@ WyslijWolny(const std::string &t)
WyslijString(t, 4); // tor wolny WyslijString(t, 4); // tor wolny
} }
#ifdef EU07_USE_OLD_GROUNDCODE
void void
WyslijNamiary(TGroundNode *t) WyslijNamiary(TGroundNode *t)
{ // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby { // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby
@@ -169,6 +170,84 @@ WyslijNamiary(TGroundNode *t)
// WriteLog("Ramka poszla!"); // WriteLog("Ramka poszla!");
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t->asName + " sent"); CommLog( Now() + " " + std::to_string(r.iComm) + " " + t->asName + " sent");
} }
#else
void
WyslijNamiary(TDynamicObject const *Vehicle)
{ // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby
// WriteLog("Wysylam pojazd");
DaneRozkaz r;
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
r.iComm = 7; // 7 - dane pojazdu
int i = 32;
size_t j = Vehicle->asName.length();
r.iPar[0] = i; // ilość danych liczbowych
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
r.fPar[2] = Vehicle->MoverParameters->Loc.X; // pozycja X
r.fPar[3] = Vehicle->MoverParameters->Loc.Y; // pozycja Y
r.fPar[4] = Vehicle->MoverParameters->Loc.Z; // pozycja Z
r.fPar[5] = Vehicle->MoverParameters->V; // prędkość ruchu X
r.fPar[6] = Vehicle->MoverParameters->nrot * M_PI *
Vehicle->MoverParameters->WheelDiameter; // prędkość obrotowa kóŁ
r.fPar[7] = 0; // prędkość ruchu Z
r.fPar[8] = Vehicle->MoverParameters->AccS; // przyspieszenie X
r.fPar[9] = Vehicle->MoverParameters->AccN; // przyspieszenie Y //na razie nie
r.fPar[10] = Vehicle->MoverParameters->AccV; // przyspieszenie Z
r.fPar[11] = Vehicle->MoverParameters->DistCounter; // przejechana odległość w km
r.fPar[12] = Vehicle->MoverParameters->PipePress; // ciśnienie w PG
r.fPar[13] = Vehicle->MoverParameters->ScndPipePress; // ciśnienie w PZ
r.fPar[14] = Vehicle->MoverParameters->BrakePress; // ciśnienie w CH
r.fPar[15] = Vehicle->MoverParameters->Compressor; // ciśnienie w ZG
r.fPar[16] = Vehicle->MoverParameters->Itot; // Prąd całkowity
r.iPar[17] = Vehicle->MoverParameters->MainCtrlPos; // Pozycja NJ
r.iPar[18] = Vehicle->MoverParameters->ScndCtrlPos; // Pozycja NB
r.iPar[19] = Vehicle->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
r.iPar[20] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[21] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1 +
Vehicle->MoverParameters->ConverterFlag * 2 +
+Vehicle->MoverParameters->CompressorFlag * 4 +
Vehicle->MoverParameters->Mains * 8 +
+Vehicle->MoverParameters->DoorLeftOpened * 16 +
Vehicle->MoverParameters->DoorRightOpened * 32 +
+Vehicle->MoverParameters->FuseFlag * 64 +
Vehicle->MoverParameters->DepartureSignal * 128;
// WriteLog("Zapisalem stare");
// WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
for (int p = 0; p < 4; p++)
{
// WriteLog("Probuje pant "+IntToStr(p));
if (p < Vehicle->iAnimType[ANIM_PANTS])
{
r.fPar[23 + p] = Vehicle->pants[p].fParamPants->PantWys; // stan pantografów 4
// WriteLog("Zapisalem pant "+IntToStr(p));
}
else
{
r.fPar[23 + p] = -2;
// WriteLog("Nie mam pant "+IntToStr(p));
}
}
// WriteLog("Zapisalem pantografy");
for (int p = 0; p < 3; p++)
r.fPar[27 + p] =
Vehicle->MoverParameters->ShowCurrent(p + 1); // amperomierze kolejnych grup
// WriteLog("zapisalem prady");
r.iPar[30] = Vehicle->MoverParameters->WarningSignal; // trabienie
r.fPar[31] = Vehicle->MoverParameters->RunningTraction.TractionVoltage; // napiecie WN
// WriteLog("Parametry gotowe");
i <<= 2; // ilość bajtów
r.cString[i] = char(j); // na końcu nazwa, żeby jakoś zidentyfikować
strcpy(r.cString + i + 1, Vehicle->asName.c_str()); // zakończony zerem
COPYDATASTRUCT cData;
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące
cData.lpData = &r;
// WriteLog("Ramka gotowa");
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
// WriteLog("Ramka poszla!");
CommLog( Now() + " " + std::to_string(r.iComm) + " " + Vehicle->asName + " sent");
}
#endif
void void
WyslijObsadzone() WyslijObsadzone()

View File

@@ -11,7 +11,11 @@ http://mozilla.org/MPL/2.0/.
#include <string> #include <string>
#ifdef EU07_USE_OLD_GROUNDCODE
class TGroundNode; class TGroundNode;
#else
class TDynamicObject;
#endif
namespace multiplayer { namespace multiplayer {
@@ -40,7 +44,11 @@ void Navigate( std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lPa
void WyslijEvent( const std::string &e, const std::string &d ); void WyslijEvent( const std::string &e, const std::string &d );
void WyslijString( const std::string &t, int n ); void WyslijString( const std::string &t, int n );
void WyslijWolny( const std::string &t ); void WyslijWolny( const std::string &t );
#ifdef EU07_USE_OLD_GROUNDCODE
void WyslijNamiary( TGroundNode *t ); void WyslijNamiary( TGroundNode *t );
#else
void WyslijNamiary( TDynamicObject const *Vehicle );
#endif
void WyslijParam( int nr, int fl ); void WyslijParam( int nr, int fl );
void WyslijUszkodzenia( const std::string &t, char fl ); void WyslijUszkodzenia( const std::string &t, char fl );
void WyslijObsadzone(); // -> skladanie wielu pojazdow void WyslijObsadzone(); // -> skladanie wielu pojazdow

View File

@@ -349,6 +349,15 @@ opengl_renderer::Render() {
void void
opengl_renderer::Render_pass( rendermode const Mode ) { opengl_renderer::Render_pass( rendermode const Mode ) {
#ifdef EU07_USE_DEBUG_CAMERA
// setup world camera for potential visualization
setup_pass(
m_worldcamera,
rendermode::color,
0.f,
1.0,
true );
#endif
setup_pass( m_renderpass, Mode ); setup_pass( m_renderpass, Mode );
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
@@ -365,14 +374,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
#endif #endif
shadowcamera = m_renderpass.camera; // cache shadow camera placement for visualization shadowcamera = m_renderpass.camera; // cache shadow camera placement for visualization
setup_pass( m_renderpass, Mode ); // restore draw mode. TBD, TODO: render mode stack setup_pass( m_renderpass, Mode ); // restore draw mode. TBD, TODO: render mode stack
#ifdef EU07_USE_DEBUG_CAMERA
setup_pass(
m_worldcamera,
rendermode::color,
0.f,
1.0,
true );
#endif
// setup shadowmap matrix // setup shadowmap matrix
m_shadowtexturematrix = m_shadowtexturematrix =
//bias from [-1, 1] to [0, 1] }; //bias from [-1, 1] to [0, 1] };
@@ -383,7 +384,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
glm::mat4{ glm::mat3{ shadowcamera.modelview() } }, glm::mat4{ glm::mat3{ shadowcamera.modelview() } },
glm::vec3{ m_renderpass.camera.position() - shadowcamera.position() } ); glm::vec3{ m_renderpass.camera.position() - shadowcamera.position() } );
} }
if( ( true == m_environmentcubetexturesupport ) if( ( true == m_environmentcubetexturesupport )
&& ( true == World.InitPerformed() ) ) { && ( true == World.InitPerformed() ) ) {
// potentially update environmental cube map // potentially update environmental cube map
@@ -391,7 +391,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
setup_pass( m_renderpass, Mode ); // restore draw mode. TBD, TODO: render mode stack setup_pass( m_renderpass, Mode ); // restore draw mode. TBD, TODO: render mode stack
} }
} }
::glViewport( 0, 0, Global::iWindowWidth, Global::iWindowHeight ); ::glViewport( 0, 0, Global::iWindowWidth, Global::iWindowHeight );
if( World.InitPerformed() ) { if( World.InitPerformed() ) {
@@ -420,7 +419,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
::glColor4f( 1.f, 0.9f, 0.8f, 1.f ); ::glColor4f( 1.f, 0.9f, 0.8f, 1.f );
::glDisable( GL_LIGHTING ); ::glDisable( GL_LIGHTING );
::glDisable( GL_TEXTURE_2D ); ::glDisable( GL_TEXTURE_2D );
if( true == Global::RenderShadows ) {
shadowcamera.draw( m_renderpass.camera.position() - shadowcamera.position() ); shadowcamera.draw( m_renderpass.camera.position() - shadowcamera.position() );
}
if( DebugCameraFlag ) { if( DebugCameraFlag ) {
::glColor4f( 0.8f, 1.f, 0.9f, 1.f ); ::glColor4f( 0.8f, 1.f, 0.9f, 1.f );
m_worldcamera.camera.draw( m_renderpass.camera.position() - m_worldcamera.camera.position() ); m_worldcamera.camera.draw( m_renderpass.camera.position() - m_worldcamera.camera.position() );
@@ -1920,7 +1921,7 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
// render // render
#ifdef EU07_USE_DEBUG_CULLING #ifdef EU07_USE_DEBUG_CULLING
// debug // debug
float const width = scene::EU07_SECTIONSIZE * 0.5f; float const width = section->m_area.radius;
float const height = scene::EU07_SECTIONSIZE * 0.2f; float const height = scene::EU07_SECTIONSIZE * 0.2f;
glDisable( GL_LIGHTING ); glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
@@ -2008,11 +2009,10 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
// first pass draws elements which we know are located in section banks, to reduce vbo switching // first pass draws elements which we know are located in section banks, to reduce vbo switching
while( First != Last ) { while( First != Last ) {
auto const *cell = First->second; auto *cell = First->second;
/*
// przeliczenia animacji torów w sektorze // przeliczenia animacji torów w sektorze
Groundsubcell->RaAnimate( m_framestamp ); cell->RaAnimate( m_framestamp );
*/
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::color: { case rendermode::color: {
// since all shapes of the section share center point we can optimize out a few calls here // since all shapes of the section share center point we can optimize out a few calls here
@@ -2023,7 +2023,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
// render // render
#ifdef EU07_USE_DEBUG_CULLING #ifdef EU07_USE_DEBUG_CULLING
// debug // debug
float const width = scene::EU07_CELLSIZE * 0.5f; float const width = cell->m_area.radius;
float const height = scene::EU07_CELLSIZE * 0.15f; float const height = scene::EU07_CELLSIZE * 0.15f;
glDisable( GL_LIGHTING ); glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
@@ -2149,24 +2149,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
void void
opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange ) { opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange ) {
/*
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
default: {
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
}
if( ( distancesquared < Node->fSquareMinRadius )
|| ( distancesquared >= Node->fSquareRadius ) ) {
return false;
}
*/
auto const &data { Shape.data() }; auto const &data { Shape.data() };
if( false == Ignorerange ) { if( false == Ignorerange ) {
@@ -3075,8 +3058,8 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// render // render
m_geometry.draw( Node->Piece->geometry ); m_geometry.draw( Node->Piece->geometry );
// ++m_debugstats.lines; ++m_debugstats.lines;
// ++m_debugstats.drawcalls; ++m_debugstats.drawcalls;
// post-render cleanup // post-render cleanup
::glPopMatrix(); ::glPopMatrix();
@@ -3183,8 +3166,9 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque
while( first != Last ) { while( first != Last ) {
auto const *cell = first->second; auto const *cell = first->second;
// TODO: include lines here
if( false == cell->m_traction.empty() ) { if( ( false == cell->m_traction.empty()
|| ( false == cell->m_lines.empty() ) ) ) {
// since all shapes of the cell share center point we can optimize out a few calls here // since all shapes of the cell share center point we can optimize out a few calls here
::glPushMatrix(); ::glPushMatrix();
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() }; auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
@@ -3196,6 +3180,7 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque
Bind_Material( null_handle ); Bind_Material( null_handle );
// render // render
for( auto *traction : cell->m_traction ) { Render_Alpha( traction ); } for( auto *traction : cell->m_traction ) { Render_Alpha( traction ); }
for( auto &lines : cell->m_lines ) { Render_Alpha( lines ); }
// post-render cleanup // post-render cleanup
::glLineWidth( 1.0 ); ::glLineWidth( 1.0 );
if( !Global::bSmoothTraction ) { if( !Global::bSmoothTraction ) {
@@ -3287,6 +3272,48 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
++m_debugstats.traction; ++m_debugstats.traction;
++m_debugstats.drawcalls; ++m_debugstats.drawcalls;
} }
void
opengl_renderer::Render_Alpha( scene::lines_node const &Lines ) {
auto const &data { Lines.data() };
double distancesquared;
switch( m_renderpass.draw_mode ) {
case rendermode::shadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = SquareMagnitude( ( data.area.center - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
default: {
distancesquared = SquareMagnitude( ( data.area.center - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
break;
}
}
if( ( distancesquared < data.rangesquared_min )
|| ( distancesquared >= data.rangesquared_max ) ) {
return;
}
// setup
auto const distance { static_cast<float>( std::sqrt( distancesquared ) ) };
auto const linealpha = (
data.line_width > 0.f ?
10.f * data.line_width
/ std::max(
0.5f * data.area.radius + 1.f,
distance - ( 0.5f * data.area.radius ) ) :
1.f ); // negative width means the lines are always opague
::glColor4fv(
glm::value_ptr(
glm::vec4{
glm::vec3{ data.lighting.diffuse * Global::DayLight.ambient }, // w zaleznosci od koloru swiatla
std::min( 1.f, linealpha ) } ) );
::glLineWidth( clamp( 0.5f * linealpha + data.line_width * data.area.radius / 1000.f, 1.f, 8.f ) );
// render
m_geometry.draw( data.geometry );
++m_debugstats.lines;
++m_debugstats.drawcalls;
}
#endif #endif
bool bool
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {

View File

@@ -340,6 +340,8 @@ private:
Render_Alpha( TAnimModel *Instance ); Render_Alpha( TAnimModel *Instance );
void void
Render_Alpha( TTraction *Traction ); Render_Alpha( TTraction *Traction );
void
Render_Alpha( scene::lines_node const &Lines );
#endif #endif
bool bool
Render_Alpha( TDynamicObject *Dynamic ); Render_Alpha( TDynamicObject *Dynamic );

238
scene.cpp
View File

@@ -130,6 +130,44 @@ basic_cell::update_traction( TDynamicObject *Vehicle, int const Pantographindex
} }
} }
// legacy method, triggers radio-stop procedure for all vehicles located on paths in the cell
void
basic_cell::radio_stop() {
for( auto *path : m_paths ) {
path->RadioStop();
}
}
// legacy method, adds specified path to the list of pieces undergoing state change
bool
basic_cell::RaTrackAnimAdd( TTrack *Track ) {
if( false == m_geometrycreated ) {
// nie ma animacji, gdy nie widać
return true;
}
if (tTrackAnim)
tTrackAnim->RaAnimListAdd(Track);
else
tTrackAnim = Track;
return false; // będzie animowane...
}
// legacy method, updates geometry for pieces in the animation list
void
basic_cell::RaAnimate( unsigned int const Framestamp ) {
if( ( tTrackAnim == nullptr )
|| ( Framestamp == m_framestamp ) ) {
// nie ma nic do animowania
return;
}
tTrackAnim = tTrackAnim->RaAnimate(); // przeliczenie animacji kolejnego
m_framestamp = Framestamp;
}
// adds provided shape to the cell // adds provided shape to the cell
void void
basic_cell::insert( shape_node Shape ) { basic_cell::insert( shape_node Shape ) {
@@ -160,15 +198,51 @@ basic_cell::insert( shape_node Shape ) {
shapes.emplace_back( Shape ); shapes.emplace_back( Shape );
} }
// adds provided lines to the cell
void
basic_cell::insert( lines_node Lines ) {
m_active = true;
auto const &linesdata { Lines.data() };
for( auto &targetlines : m_lines ) {
// try to merge shapes with matching view ranges...
auto const &targetlinesdata { targetlines.data() };
if( ( linesdata.rangesquared_min == targetlinesdata.rangesquared_min )
&& ( linesdata.rangesquared_max == targetlinesdata.rangesquared_max )
// ...and located close to each other (within arbitrary limit of 10m)
&& ( glm::length( linesdata.area.center - targetlinesdata.area.center ) < 10.0 ) ) {
if( true == targetlines.merge( Lines ) ) {
// if the shape was merged there's nothing left to do
return;
}
}
}
// otherwise add the shape to the relevant list
Lines.origin( m_area.center );
m_lines.emplace_back( Lines );
}
// adds provided path to the cell // adds provided path to the cell
void void
basic_cell::insert( TTrack *Path ) { basic_cell::insert( TTrack *Path ) {
m_active = true; m_active = true;
// TODO: add animation hook
Path->origin( m_area.center ); Path->origin( m_area.center );
m_paths.emplace_back( Path ); m_paths.emplace_back( Path );
// animation hook
#ifndef EU07_USE_OLD_GROUNDCODE
Path->RaOwnerSet( this );
#endif
// re-calculate cell radius, in case track extends outside the cell's boundaries
auto endpoints = Path->endpoints();
for( auto &endpoint : endpoints ) {
m_area.radius = std::max<float>(
m_area.radius,
glm::length( m_area.center - endpoint ) + 25.f ); // extra margin to prevent driven vehicle from flicking
}
} }
// adds provided traction piece to the cell // adds provided traction piece to the cell
@@ -179,6 +253,13 @@ basic_cell::insert( TTraction *Traction ) {
Traction->origin( m_area.center ); Traction->origin( m_area.center );
m_traction.emplace_back( Traction ); m_traction.emplace_back( Traction );
// re-calculate cell radius, in case traction piece extends outside the cell's boundaries
auto endpoints = Traction->endpoints();
for( auto &endpoint : endpoints ) {
m_area.radius = std::max<float>(
m_area.radius,
glm::length( m_area.center - endpoint ) ); // adding arbitrary safety margin
}
} }
// adds provided model instance to the cell // adds provided model instance to the cell
@@ -203,6 +284,15 @@ basic_cell::insert( TAnimModel *Instance ) {
// opaque pieces // opaque pieces
m_instancesopaque.emplace_back( Instance ); m_instancesopaque.emplace_back( Instance );
} }
// re-calculate cell radius, in case model extends outside the cell's boundaries
if( Instance->Model() ) {
auto const modelradius{ Instance->Model()->bounding_radius() };
if( modelradius > 0.f ) {
m_area.radius = std::max<float>(
m_area.radius,
glm::length( m_area.center - Instance->location() ) + modelradius ); // adding arbitrary safety margin
}
}
} }
// adds provided sound instance to the cell // adds provided sound instance to the cell
@@ -251,7 +341,7 @@ basic_cell::register_end( TTraction *Traction ) {
// find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance // find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
basic_cell::find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ) { basic_cell::find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) {
TDynamicObject *vehiclenearest { nullptr }; TDynamicObject *vehiclenearest { nullptr };
float leastdistance { std::numeric_limits<float>::max() }; float leastdistance { std::numeric_limits<float>::max() };
@@ -264,7 +354,16 @@ basic_cell::find( glm::dvec3 const &Point, float const Radius, bool const Onlyco
&& ( vehicle->Mechanik == nullptr ) ) { && ( vehicle->Mechanik == nullptr ) ) {
continue; continue;
} }
if( false == Findbycoupler ) {
// basic search, checks vehicles' center points
distance = glm::length2( glm::dvec3{ vehicle->GetPosition() } - Point ); distance = glm::length2( glm::dvec3{ vehicle->GetPosition() } - Point );
}
else {
// alternative search, checks positions of vehicles' couplers
distance = std::min(
glm::length2( glm::dvec3{ vehicle->HeadPosition() } - Point ),
glm::length2( glm::dvec3{ vehicle->RearPosition() } - Point ) );
}
if( ( distance > distancecutoff ) if( ( distance > distancecutoff )
|| ( distance > leastdistance ) ){ || ( distance > leastdistance ) ){
continue; continue;
@@ -372,10 +471,13 @@ basic_cell::create_geometry( geometrybank_handle const &Bank ) {
for( auto *path : m_paths ) { path->create_geometry( Bank ); } for( auto *path : m_paths ) { path->create_geometry( Bank ); }
for( auto *traction : m_traction ) { traction->create_geometry( Bank ); } for( auto *traction : m_traction ) { traction->create_geometry( Bank ); }
#endif #endif
for( auto &lines : m_lines ) { lines.create_geometry( Bank ); }
// arrange content by assigned materials to minimize state switching // arrange content by assigned materials to minimize state switching
std::sort( std::sort(
std::begin( m_paths ), std::end( m_paths ), std::begin( m_paths ), std::end( m_paths ),
TTrack::sort_by_material ); TTrack::sort_by_material );
m_geometrycreated = true; // helper for legacy animation code, get rid of it after refactoring
} }
@@ -384,11 +486,9 @@ basic_cell::create_geometry( geometrybank_handle const &Bank ) {
void void
basic_section::update( glm::dvec3 const &Location, float const Radius ) { basic_section::update( glm::dvec3 const &Location, float const Radius ) {
auto const squaredradii { std::pow( ( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) + Radius, 2 ) };
for( auto &cell : m_cells ) { for( auto &cell : m_cells ) {
if( glm::length2( cell.area().center - Location ) < squaredradii ) { if( glm::length2( cell.area().center - Location ) < ( ( cell.area().radius + Radius ) * ( cell.area().radius + Radius ) ) ) {
// we reject cells which aren't within our area of interest // we reject cells which aren't within our area of interest
cell.update(); cell.update();
} }
@@ -408,16 +508,28 @@ basic_section::update_traction( TDynamicObject *Vehicle, int const Pantographind
auto const pantographposition = position + ( vLeft * pantograph->vPos.z ) + ( vUp * pantograph->vPos.y ) + ( vFront * pantograph->vPos.x ); auto const pantographposition = position + ( vLeft * pantograph->vPos.z ) + ( vUp * pantograph->vPos.y ) + ( vFront * pantograph->vPos.x );
auto const radius { 0.0 }; // { EU07_CELLSIZE * 0.5 }; // experimentally limited, check if it has any negative effect auto const radius { 0.0 }; // { EU07_CELLSIZE * 0.5 }; // experimentally limited, check if it has any negative effect
auto const squaredradii { std::pow( ( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) + radius, 2 ) };
for( auto &cell : m_cells ) { for( auto &cell : m_cells ) {
// we reject early cells which aren't within our area of interest // we reject early cells which aren't within our area of interest
if( glm::length2( cell.area().center - pantographposition ) < squaredradii ) { if( glm::length2( cell.area().center - pantographposition ) < ( ( cell.area().radius + radius ) * ( cell.area().radius + radius ) ) ) {
cell.update_traction( Vehicle, Pantographindex ); cell.update_traction( Vehicle, Pantographindex );
} }
} }
} }
// legacy method, triggers radio-stop procedure for all vehicles in 2km radius around specified location
void
basic_section::radio_stop( glm::dvec3 const &Location, float const Radius ) {
for( auto &cell : m_cells ) {
if( glm::length2( cell.area().center - Location ) < ( ( cell.area().radius + Radius ) * ( cell.area().radius + Radius ) ) ) {
// we reject cells which aren't within our area of interest
cell.radio_stop();
}
}
}
// adds provided shape to the section // adds provided shape to the section
void void
basic_section::insert( shape_node Shape ) { basic_section::insert( shape_node Shape ) {
@@ -444,9 +556,16 @@ basic_section::insert( shape_node Shape ) {
} }
} }
// adds provided lines to the section
void
basic_section::insert( lines_node Lines ) {
cell( Lines.data().area.center ).insert( Lines );
}
// find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance // find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
basic_section::find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ) { basic_section::find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) {
// go through sections within radius of interest, and pick the nearest candidate // go through sections within radius of interest, and pick the nearest candidate
TDynamicObject TDynamicObject
@@ -456,14 +575,12 @@ basic_section::find( glm::dvec3 const &Point, float const Radius, bool const Onl
distancefound, distancefound,
distancenearest { std::numeric_limits<float>::max() }; distancenearest { std::numeric_limits<float>::max() };
auto const squaredradii { std::pow( ( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) + Radius, 2 ) };
for( auto &cell : m_cells ) { for( auto &cell : m_cells ) {
// we reject early cells which aren't within our area of interest // we reject early cells which aren't within our area of interest
if( glm::length2( cell.area().center - Point ) > squaredradii ) { if( glm::length2( cell.area().center - Point ) > ( ( cell.area().radius + Radius ) * ( cell.area().radius + Radius ) ) ) {
continue; continue;
} }
std::tie( vehiclefound, distancefound ) = cell.find( Point, Radius, Onlycontrolled ); std::tie( vehiclefound, distancefound ) = cell.find( Point, Radius, Onlycontrolled, Findbycoupler );
if( ( vehiclefound != nullptr ) if( ( vehiclefound != nullptr )
&& ( distancefound < distancenearest ) ) { && ( distancefound < distancenearest ) ) {
@@ -503,11 +620,10 @@ basic_section::find( glm::dvec3 const &Point, TTraction const *Other, int const
endpointnearest { -1 }; endpointnearest { -1 };
auto const radius { 0.0 }; // { EU07_CELLSIZE * 0.5 }; // experimentally limited, check if it has any negative effect auto const radius { 0.0 }; // { EU07_CELLSIZE * 0.5 }; // experimentally limited, check if it has any negative effect
auto const squaredradii { std::pow( ( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) + radius, 2 ) };
for( auto &cell : m_cells ) { for( auto &cell : m_cells ) {
// we reject early cells which aren't within our area of interest // we reject early cells which aren't within our area of interest
if( glm::length2( cell.area().center - Point ) > squaredradii ) { if( glm::length2( cell.area().center - Point ) > ( ( cell.area().radius + radius ) * ( cell.area().radius + radius ) ) ) {
continue; continue;
} }
std::tie( tractionfound, endpointfound, distancefound ) = cell.find( Point, Other, Currentdirection ); std::tie( tractionfound, endpointfound, distancefound ) = cell.find( Point, Other, Currentdirection );
@@ -618,8 +734,49 @@ basic_region::update_traction( TDynamicObject *Vehicle, int const Pantographinde
} }
} }
// legacy method, links specified path piece with potential neighbours
void void
basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) { basic_region::TrackJoin( TTrack *Track ) {
// wyszukiwanie sąsiednich torów do podłączenia (wydzielone na użytek obrotnicy)
TTrack *matchingtrack;
int endpointid;
if( Track->CurrentPrev() == nullptr ) {
std::tie( matchingtrack, endpointid ) = find_path( Track->CurrentSegment()->FastGetPoint_0(), Track );
switch( endpointid ) {
case 0:
Track->ConnectPrevPrev( matchingtrack, 0 );
break;
case 1:
Track->ConnectPrevNext( matchingtrack, 1 );
break;
}
}
if( Track->CurrentNext() == nullptr ) {
std::tie( matchingtrack, endpointid ) = find_path( Track->CurrentSegment()->FastGetPoint_1(), Track );
switch( endpointid ) {
case 0:
Track->ConnectNextPrev( matchingtrack, 0 );
break;
case 1:
Track->ConnectNextNext( matchingtrack, 1 );
break;
}
}
}
// legacy method, triggers radio-stop procedure for all vehicles in 2km radius around specified location
void
basic_region::RadioStop( glm::dvec3 const &Location ) {
auto const range = 2000.f;
auto const &sectionlist = sections( Location, range );
for( auto *section : sectionlist ) {
section->radio_stop( Location, range );
}
}
void
basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform ) {
// shape might need to be split into smaller pieces, so we create list of nodes instead of just single one // shape might need to be split into smaller pieces, so we create list of nodes instead of just single one
// using deque so we can do single pass iterating and addding generated pieces without invalidating anything // using deque so we can do single pass iterating and addding generated pieces without invalidating anything
@@ -628,6 +785,8 @@ basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) {
if( shape.m_data.vertices.empty() ) { return; } if( shape.m_data.vertices.empty() ) { return; }
// adjust input if necessary: // adjust input if necessary:
if( true == Transform ) {
// shapes generated from legacy terrain come with world space coordinates and don't need processing
if( Scratchpad.location_rotation != glm::vec3( 0, 0, 0 ) ) { if( Scratchpad.location_rotation != glm::vec3( 0, 0, 0 ) ) {
// rotate... // rotate...
auto const rotation = glm::radians( Scratchpad.location_rotation ); auto const rotation = glm::radians( Scratchpad.location_rotation );
@@ -661,6 +820,7 @@ basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) {
// with the trimming done we can calculate shape's bounding radius // with the trimming done we can calculate shape's bounding radius
shape.compute_radius(); shape.compute_radius();
} }
}
// move the data into appropriate section(s) // move the data into appropriate section(s)
for( auto &shape : shapes ) { for( auto &shape : shapes ) {
@@ -679,6 +839,50 @@ basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) {
} }
} }
// inserts provided lines in the region
void
basic_region::insert_lines( lines_node Lines, scratch_data &Scratchpad ) {
if( Lines.m_data.vertices.empty() ) { return; }
// transform point coordinates if needed
if( Scratchpad.location_rotation != glm::vec3( 0, 0, 0 ) ) {
// rotate...
auto const rotation = glm::radians( Scratchpad.location_rotation );
for( auto &vertex : Lines.m_data.vertices ) {
vertex.position = glm::rotateZ<double>( vertex.position, rotation.z );
vertex.position = glm::rotateX<double>( vertex.position, rotation.x );
vertex.position = glm::rotateY<double>( vertex.position, rotation.y );
}
}
if( ( false == Scratchpad.location_offset.empty() )
&& ( Scratchpad.location_offset.top() != glm::dvec3( 0, 0, 0 ) ) ) {
// ...and move
auto const offset = Scratchpad.location_offset.top();
for( auto &vertex : Lines.m_data.vertices ) {
vertex.position += offset;
}
}
// calculate bounding area
for( auto const &vertex : Lines.m_data.vertices ) {
Lines.m_data.area.center += vertex.position;
}
Lines.m_data.area.center /= Lines.m_data.vertices.size();
Lines.compute_radius();
// move the data into appropriate section
if( point_inside( Lines.m_data.area.center ) ) {
// NOTE: nodes placed outside of region boundaries are discarded
section( Lines.m_data.area.center ).insert( Lines );
}
else {
ErrorLog(
"Bad scenario: lines node" + (
Lines.m_name.empty() ?
"" :
" \"" + Lines.m_name + "\"" )
+ " placed in location outside region bounds (" + to_string( Lines.m_data.area.center ) + ")" );
}
}
// inserts provided track in the region // inserts provided track in the region
void void
basic_region::insert_path( TTrack *Path, scratch_data &Scratchpad ) { basic_region::insert_path( TTrack *Path, scratch_data &Scratchpad ) {
@@ -776,7 +980,7 @@ basic_region::insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpa
// find a vehicle located neares to specified location, within specified radius, optionally discarding vehicles without drivers // find a vehicle located neares to specified location, within specified radius, optionally discarding vehicles without drivers
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ) { basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) {
auto const &sectionlist = sections( Point, Radius ); auto const &sectionlist = sections( Point, Radius );
// go through sections within radius of interest, and pick the nearest candidate // go through sections within radius of interest, and pick the nearest candidate
@@ -788,7 +992,7 @@ basic_region::find_vehicle( glm::dvec3 const &Point, float const Radius, bool co
nearestdistance { std::numeric_limits<float>::max() }; nearestdistance { std::numeric_limits<float>::max() };
for( auto *section : sectionlist ) { for( auto *section : sectionlist ) {
std::tie( foundvehicle, founddistance ) = section->find( Point, Radius, Onlycontrolled ); std::tie( foundvehicle, founddistance ) = section->find( Point, Radius, Onlycontrolled, Findbycoupler );
if( ( foundvehicle != nullptr ) if( ( foundvehicle != nullptr )
&& ( founddistance < nearestdistance ) ) { && ( founddistance < nearestdistance ) ) {

58
scene.h
View File

@@ -61,9 +61,21 @@ public:
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void void
update_traction( TDynamicObject *Vehicle, int const Pantographindex ); update_traction( TDynamicObject *Vehicle, int const Pantographindex );
// legacy method, triggers radio-stop procedure for all vehicles located on paths in the cell
void
radio_stop();
// legacy method, adds specified path to the list of pieces undergoing state change
bool
RaTrackAnimAdd( TTrack *Track );
// legacy method, updates geometry for pieces in the animation list
void
RaAnimate( unsigned int const Framestamp );
// adds provided shape to the cell // adds provided shape to the cell
void void
insert( shape_node Shape ); insert( shape_node Shape );
// adds provided lines to the cell
void
insert( lines_node Lines );
// adds provided path to the cell // adds provided path to the cell
void void
insert( TTrack *Path ); insert( TTrack *Path );
@@ -85,9 +97,9 @@ public:
// registers provided traction piece in the lookup directory of the cell // registers provided traction piece in the lookup directory of the cell
void void
register_end( TTraction *Traction ); register_end( TTraction *Traction );
// find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance // find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ); find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
// finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint // finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint
std::tuple<TTrack *, int> std::tuple<TTrack *, int>
find( glm::dvec3 const &Point, TTrack const *Exclude ); find( glm::dvec3 const &Point, TTrack const *Exclude );
@@ -111,19 +123,19 @@ public:
private: private:
// types // types
using shapenode_sequence = std::vector<shape_node>; using shapenode_sequence = std::vector<shape_node>;
using linesnode_sequence = std::vector<lines_node>;
using path_sequence = std::vector<TTrack *>; using path_sequence = std::vector<TTrack *>;
// using path_set = std::unordered_set<TTrack *>;
using traction_sequence = std::vector<TTraction *>; using traction_sequence = std::vector<TTraction *>;
// using traction_set = std::unordered_set<TTraction *>;
using instance_sequence = std::vector<TAnimModel *>; using instance_sequence = std::vector<TAnimModel *>;
using sound_sequence = std::vector<TTextSound *>; using sound_sequence = std::vector<TTextSound *>;
using eventlauncher_sequence = std::vector<TEventLauncher *>; using eventlauncher_sequence = std::vector<TEventLauncher *>;
// members // members
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) }; scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE ) };
bool m_active { false }; // whether the cell holds any actual data bool m_active { false }; // whether the cell holds any actual data
// content // content
shapenode_sequence m_shapesopaque; // opaque pieces of geometry shapenode_sequence m_shapesopaque; // opaque pieces of geometry
shapenode_sequence m_shapestranslucent; // translucent pieces of geometry shapenode_sequence m_shapestranslucent; // translucent pieces of geometry
linesnode_sequence m_lines;
path_sequence m_paths; // path pieces path_sequence m_paths; // path pieces
instance_sequence m_instancesopaque; instance_sequence m_instancesopaque;
instance_sequence m_instancetranslucent; instance_sequence m_instancetranslucent;
@@ -135,6 +147,10 @@ private:
path_sequence paths; path_sequence paths;
traction_sequence traction; traction_sequence traction;
} m_directories; } m_directories;
// animation of owned items (legacy code, clean up along with track refactoring)
bool m_geometrycreated { false };
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji
}; };
// basic scene partitioning structure, holds terrain geometry and collection of cells // basic scene partitioning structure, holds terrain geometry and collection of cells
@@ -150,22 +166,33 @@ public:
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void void
update_traction( TDynamicObject *Vehicle, int const Pantographindex ); update_traction( TDynamicObject *Vehicle, int const Pantographindex );
// legacy method, triggers radio-stop procedure for all vehicles in 2km radius around specified location
void
radio_stop( glm::dvec3 const &Location, float const Radius );
// adds provided shape to the section // adds provided shape to the section
void void
insert( shape_node Shape ); insert( shape_node Shape );
// adds provided lines to the section
void
insert( lines_node Lines );
// adds provided node to the section // adds provided node to the section
template <class Type_> template <class Type_>
void void
insert( Type_ *Node ) { insert( Type_ *Node ) {
cell( Node->location() ).insert( Node ); } auto &targetcell { cell( Node->location() ) };
targetcell.insert( Node );
// some node types can extend bounding area of the target cell
m_area.radius = std::max<float>(
m_area.radius,
glm::length( m_area.center - targetcell.area().center ) + targetcell.area().radius ); }
// registers provided node in the lookup directory of the section enclosing specified point // registers provided node in the lookup directory of the section enclosing specified point
template <class Type_> template <class Type_>
void void
register_node( Type_ *Node, glm::dvec3 const &Point ) { register_node( Type_ *Node, glm::dvec3 const &Point ) {
cell( Point ).register_end( Node ); } cell( Point ).register_end( Node ); }
// find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance // find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ); find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
// finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint // finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint
std::tuple<TTrack *, int> std::tuple<TTrack *, int>
find( glm::dvec3 const &Point, TTrack const *Exclude ); find( glm::dvec3 const &Point, TTrack const *Exclude );
@@ -223,9 +250,18 @@ public:
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle // legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
void void
update_traction( TDynamicObject *Vehicle, int const Pantographindex ); update_traction( TDynamicObject *Vehicle, int const Pantographindex );
// legacy method, links specified path piece with potential neighbours
void
TrackJoin( TTrack *Track );
// legacy method, triggers radio-stop procedure for all vehicles in 2km radius around specified location
void
RadioStop( glm::dvec3 const &Location );
// inserts provided shape in the region // inserts provided shape in the region
void void
insert_shape( shape_node Shape, scratch_data &Scratchpad ); insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform );
// inserts provided lines in the region
void
insert_lines( lines_node Lines, scratch_data &Scratchpad );
// inserts provided track in the region // inserts provided track in the region
void void
insert_path( TTrack *Path, scratch_data &Scratchpad ); insert_path( TTrack *Path, scratch_data &Scratchpad );
@@ -241,9 +277,9 @@ public:
// inserts provided event launcher in the region // inserts provided event launcher in the region
void void
insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad ); insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad );
// find a vehicle located nearest to specified point, within specified radius, optionally ignoring vehicles without drivers. reurns: located vehicle and distance // find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float> std::tuple<TDynamicObject *, float>
find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ); find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
// finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint // finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint
std::tuple<TTrack *, int> std::tuple<TTrack *, int>
find_path( glm::dvec3 const &Point, TTrack const *Exclude ); find_path( glm::dvec3 const &Point, TTrack const *Exclude );

View File

@@ -207,6 +207,65 @@ shape_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
return *this; return *this;
} }
// imports data from provided submodel
shape_node &
shape_node::convert( TSubModel const *Submodel ) {
m_name = Submodel->pName;
m_data.lighting.ambient = Submodel->f4Ambient;
m_data.lighting.diffuse = Submodel->f4Diffuse;
m_data.lighting.specular = Submodel->f4Specular;
m_data.material = Submodel->m_material;
m_data.translucent = ( true == GfxRenderer.Material( m_data.material ).has_alpha );
// NOTE: we set unlimited view range typical for terrain, because we don't expect to convert any other 3d models
m_data.rangesquared_max = std::numeric_limits<double>::max();
if( Submodel->m_geometry == null_handle ) { return *this; }
int vertexcount { 0 };
std::vector<world_vertex> importedvertices;
world_vertex vertex, vertex1, vertex2;
for( auto const &sourcevertex : GfxRenderer.Vertices( Submodel->m_geometry ) ) {
vertex.position = sourcevertex.position;
vertex.normal = sourcevertex.normal;
vertex.texture = sourcevertex.texture;
if( vertexcount == 0 ) { vertex1 = vertex; }
else if( vertexcount == 1 ) { vertex2 = vertex; }
else if( vertexcount >= 2 ) {
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
importedvertices.emplace_back( vertex1 );
importedvertices.emplace_back( vertex2 );
importedvertices.emplace_back( vertex );
}
// start a new triangle
vertexcount = -1;
}
++vertexcount;
}
if( true == importedvertices.empty() ) { return *this; }
// assign imported geometry to the node...
m_data.vertices.swap( importedvertices );
// ...and calculate center...
for( auto const &vertex : m_data.vertices ) {
m_data.area.center += vertex.position;
}
m_data.area.center /= m_data.vertices.size();
// ...and bounding area
double squareradius { 0.0 };
for( auto const &vertex : m_data.vertices ) {
squareradius = std::max(
squareradius,
glm::length2( vertex.position - m_data.area.center ) );
}
m_data.area.radius = std::max<float>(
m_data.area.radius,
std::sqrt( squareradius ) );
return *this;
}
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed // adds content of provided node to already enclosed geometry. returns: true if merge could be performed
bool bool
shape_node::merge( shape_node &Shape ) { shape_node::merge( shape_node &Shape ) {
@@ -260,6 +319,151 @@ shape_node::compute_radius() {
} }
// restores content of the node from provded input stream
lines_node &
lines_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
// import common data
m_name = Nodedata.name;
m_data.rangesquared_min = Nodedata.range_min * Nodedata.range_min;
m_data.rangesquared_max = (
Nodedata.range_max >= 0.0 ?
Nodedata.range_max * Nodedata.range_max :
std::numeric_limits<double>::max() );
// material
Input.getTokens( 3, false );
Input
>> m_data.lighting.diffuse.r
>> m_data.lighting.diffuse.g
>> m_data.lighting.diffuse.b;
m_data.lighting.diffuse /= 255.f;
m_data.lighting.diffuse.a = 1.f;
Input.getTokens( 1, false );
Input
>> m_data.line_width;
m_data.line_width = std::min( 30.f, m_data.line_width ); // 30 pix equals rougly width of a signal pole viewed from ~1m away
// geometry
enum subtype {
lines,
line_strip,
line_loop
} const nodetype = (
Nodedata.type == "lines" ? lines :
Nodedata.type == "line_strip" ? line_strip :
line_loop );
std::size_t vertexcount { 0 };
world_vertex vertex, vertex0, vertex1;
std::string token = Input.getToken<std::string>();
do {
vertex.position.x = std::atof( token.c_str() );
Input.getTokens( 2, false );
Input
>> vertex.position.y
>> vertex.position.z;
// convert all data to gl_lines to allow data merge for matching nodes
switch( nodetype ) {
case lines: {
m_data.vertices.emplace_back( vertex );
break;
}
case line_strip: {
if( vertexcount > 0 ) {
m_data.vertices.emplace_back( vertex1 );
m_data.vertices.emplace_back( vertex );
}
vertex1 = vertex;
++vertexcount;
break;
}
case line_loop: {
if( vertexcount == 0 ) {
vertex0 = vertex;
vertex1 = vertex;
}
else {
m_data.vertices.emplace_back( vertex1 );
m_data.vertices.emplace_back( vertex );
}
vertex1 = vertex;
++vertexcount;
break;
}
default: { break; }
}
token = Input.getToken<std::string>();
} while( token != "endline" );
// add closing line for the loop
if( ( nodetype == line_loop )
&& ( vertexcount > 2 ) ) {
m_data.vertices.emplace_back( vertex1 );
m_data.vertices.emplace_back( vertex0 );
}
if( m_data.vertices.size() % 2 != 0 ) {
ErrorLog( "Lines node specified odd number of vertices, encountered in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
m_data.vertices.pop_back();
}
return *this;
}
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
bool
lines_node::merge( lines_node &Lines ) {
if( ( m_data.line_width != Lines.m_data.line_width )
|| ( m_data.lighting != Lines.m_data.lighting ) ) {
// can't merge nodes with different appearance
return false;
}
// add geometry from provided node
m_data.area.center =
interpolate(
m_data.area.center, Lines.m_data.area.center,
static_cast<float>( Lines.m_data.vertices.size() ) / ( Lines.m_data.vertices.size() + m_data.vertices.size() ) );
m_data.vertices.insert(
std::end( m_data.vertices ),
std::begin( Lines.m_data.vertices ), std::end( Lines.m_data.vertices ) );
// NOTE: we could recalculate radius with something other than brute force, but it'll do
compute_radius();
return true;
}
// generates renderable version of held non-instanced geometry in specified geometry bank
void
lines_node::create_geometry( geometrybank_handle const &Bank ) {
vertex_array vertices; vertices.reserve( m_data.vertices.size() );
for( auto const &vertex : m_data.vertices ) {
vertices.emplace_back(
vertex.position - m_data.origin,
vertex.normal,
vertex.texture );
}
m_data.geometry = GfxRenderer.Insert( vertices, Bank, GL_LINES );
std::vector<world_vertex>().swap( m_data.vertices ); // hipster shrink_to_fit
}
// calculates node's bounding radius
void
lines_node::compute_radius() {
auto squaredradius { 0.0 };
for( auto const &vertex : m_data.vertices ) {
squaredradius = std::max(
squaredradius,
glm::length2( vertex.position - m_data.area.center ) );
}
m_data.area.radius = static_cast<float>( std::sqrt( squaredradius ) );
}
/* /*
memory_node & memory_node &
memory_node::deserialize( cParser &Input, node_data const &Nodedata ) { memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
@@ -279,6 +483,8 @@ memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
*/ */
} // scene } // scene
namespace editor { namespace editor {
basic_node::basic_node( scene::node_data const &Nodedata ) : basic_node::basic_node( scene::node_data const &Nodedata ) :

View File

@@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include "vertex.h" #include "vertex.h"
#include "openglgeometrybank.h" #include "openglgeometrybank.h"
#include "parser.h" #include "parser.h"
#include "model3d.h"
struct lighting_data { struct lighting_data {
@@ -104,6 +105,9 @@ public:
// restores content of the node from provded input stream // restores content of the node from provded input stream
shape_node & shape_node &
deserialize( cParser &Input, scene::node_data const &Nodedata ); deserialize( cParser &Input, scene::node_data const &Nodedata );
// imports data from provided submodel
shape_node &
convert( TSubModel const *Submodel );
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed // adds content of provided node to already enclosed geometry. returns: true if merge could be performed
bool bool
merge( shape_node &Shape ); merge( shape_node &Shape );
@@ -132,6 +136,59 @@ private:
shapenode_data m_data; shapenode_data m_data;
}; };
// holds a group of untextured lines
class lines_node {
friend class basic_region; // region might want to modify node content when it's being inserted
public:
// types
struct linesnode_data {
// placement and visibility
scene::bounding_area area; // bounding area, in world coordinates
bool visible { true }; // visibility flag
double rangesquared_min { 0.0 }; // visibility range, min
double rangesquared_max { 0.0 }; // visibility range, max
// material data
lighting_data lighting;
float line_width; // thickness of stored lines
// geometry data
std::vector<world_vertex> vertices; // world space source data of the geometry
glm::dvec3 origin; // world position of the relative coordinate system origin
geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer
};
// methods
// restores content of the node from provded input stream
lines_node &
deserialize( cParser &Input, scene::node_data const &Nodedata );
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
bool
merge( lines_node &Lines );
// generates renderable version of held non-instanced geometry in specified geometry bank
void
create_geometry( geometrybank_handle const &Bank );
// calculates shape's bounding radius
void
compute_radius();
// set visibility
void
visible( bool State ) {
m_data.visible = State; }
// set origin point
void
origin( glm::dvec3 Origin ) {
m_data.origin = Origin; }
// data access
linesnode_data const &
data() const {
return m_data; }
private:
// members
std::string m_name;
linesnode_data m_data;
};
/* /*
// holds geometry for specific piece of track/road/waterway // holds geometry for specific piece of track/road/waterway

View File

@@ -352,7 +352,29 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
if( nodedata.range_min < 0.0 ) { if( nodedata.range_min < 0.0 ) {
// convert and import 3d terrain // convert and import 3d terrain
// TODO: implement this auto *instance { deserialize_model( Input, Scratchpad, nodedata ) };
// model import can potentially fail
if( instance == nullptr ) { return; }
// go through submodels, and import them as shapes
auto const cellcount = instance->TerrainCount() + 1; // zliczenie submodeli
for( auto i = 1; i < cellcount; ++i ) {
auto *submodel = instance->TerrainSquare( i - 1 );
simulation::Region->insert_shape(
scene::shape_node().convert( submodel ),
Scratchpad,
false );
// if there's more than one group of triangles in the cell they're held as children of the primary submodel
submodel = submodel->ChildGet();
while( submodel != nullptr ) {
simulation::Region->insert_shape(
scene::shape_node().convert( submodel ),
Scratchpad,
false );
submodel = submodel->NextGet();
}
}
// with the import done we can get rid of the source model
delete instance;
} }
else { else {
// regular instance of 3d mesh // regular instance of 3d mesh
@@ -372,14 +394,20 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|| ( nodedata.type == "triangle_strip" ) || ( nodedata.type == "triangle_strip" )
|| ( nodedata.type == "triangle_fan" ) ) { || ( nodedata.type == "triangle_fan" ) ) {
simulation::Region->insert_shape( scene::shape_node().deserialize( Input, nodedata ), Scratchpad ); simulation::Region->insert_shape(
scene::shape_node().deserialize(
Input, nodedata ),
Scratchpad,
true );
} }
else if( ( nodedata.type == "lines" ) else if( ( nodedata.type == "lines" )
|| ( nodedata.type == "line_strip" ) || ( nodedata.type == "line_strip" )
|| ( nodedata.type == "line_loop" ) ) { || ( nodedata.type == "line_loop" ) ) {
// TODO: implement simulation::Region->insert_lines(
skip_until( Input, "endline" ); scene::lines_node().deserialize(
Input, nodedata ),
Scratchpad );
} }
else if( nodedata.type == "memcell" ) { else if( nodedata.type == "memcell" ) {