mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
continued refactoring: lines, terrain models; render culling optimizations and fixes
This commit is contained in:
@@ -232,9 +232,14 @@ void TAnimContainer::UpdateModel() {
|
||||
fTranslateSpeed = 0.0; // wyłączenie przeliczania wektora
|
||||
if (LengthSquared3(vTranslation) <= 0.0001) // jeśli jest w punkcie początkowym
|
||||
iAnim &= ~2; // wyłączyć zmianę pozycji submodelu
|
||||
if (evDone)
|
||||
Global::AddToQuery(evDone, NULL); // wykonanie eventu informującego o
|
||||
// zakończeniu
|
||||
if( evDone ) {
|
||||
// wykonanie eventu informującego o zakończeniu
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Global::AddToQuery( evDone, NULL );
|
||||
#else
|
||||
simulation::Events.AddToQuery( evDone, nullptr );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fRotateSpeed != 0.0)
|
||||
@@ -299,9 +304,14 @@ void TAnimContainer::UpdateModel() {
|
||||
if (!anim)
|
||||
{ // nie potrzeba przeliczać już
|
||||
fRotateSpeed = 0.0;
|
||||
if (evDone)
|
||||
Global::AddToQuery(evDone, NULL); // wykonanie eventu informującego o
|
||||
// zakończeniu
|
||||
if( evDone ) {
|
||||
// wykonanie eventu informującego o zakończeniu
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Global::AddToQuery( evDone, NULL );
|
||||
#else
|
||||
simulation::Events.AddToQuery( evDone, nullptr );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if( fAngleSpeed != 0.f ) {
|
||||
@@ -330,7 +340,11 @@ void TAnimContainer::PrepareModel()
|
||||
fAngleSpeed = 0.0; // wyłączenie przeliczania wektora
|
||||
if( evDone ) {
|
||||
// wykonanie eventu informującego o zakończeniu
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Global::AddToQuery( evDone, NULL );
|
||||
#else
|
||||
simulation::Events.AddToQuery( evDone, nullptr );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -149,6 +149,10 @@ public:
|
||||
material_data const *
|
||||
Material() const {
|
||||
return &m_materialdata; }
|
||||
inline
|
||||
TModel3d *
|
||||
Model() {
|
||||
return pModel; }
|
||||
// members
|
||||
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -37,8 +34,8 @@ void TCamera::Init(vector3 NPos, vector3 NAngle)
|
||||
void TCamera::OnCursorMove(double x, double y)
|
||||
{
|
||||
// McZapkie-170402: zeby mysz dzialala zawsze if (Type==tp_Follow)
|
||||
Pitch += y;
|
||||
Yaw += -x;
|
||||
Yaw -= x;
|
||||
Pitch -= y;
|
||||
if (Yaw > M_PI)
|
||||
Yaw -= 2 * M_PI;
|
||||
else if (Yaw < -M_PI)
|
||||
@@ -62,7 +59,7 @@ TCamera::OnCommand( command_data const &Command ) {
|
||||
|
||||
OnCursorMove(
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
15
DynObj.cpp
15
DynObj.cpp
@@ -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 );
|
||||
}
|
||||
|
||||
3
DynObj.h
3
DynObj.h
@@ -495,6 +495,9 @@ public:
|
||||
// legacy method, checks for presence and height of traction wire for specified vehicle
|
||||
void
|
||||
update_traction( TDynamicObject *Vehicle );
|
||||
// legacy method, sends list of vehicles over network
|
||||
void
|
||||
DynamicList( bool const Onlycontrolled = false ) const;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
40
Event.cpp
40
Event.cpp
@@ -46,8 +46,7 @@ TEvent::~TEvent() {
|
||||
switch (Type)
|
||||
{ // sprzątanie
|
||||
case tp_Multiple:
|
||||
// SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa obiektu powiązanego zamieniana na
|
||||
// wskaźnik
|
||||
// SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa obiektu powiązanego zamieniana na wskaźnik
|
||||
if (iFlags & conditional_memstring) // o ile jest łańcuch do porównania w memcompare
|
||||
SafeDeleteArray(Params[10].asText);
|
||||
break;
|
||||
@@ -82,8 +81,7 @@ void TEvent::Conditions(cParser *parser, std::string s)
|
||||
if (!asNodeName.empty())
|
||||
{ // podczepienie łańcucha, jeśli nie jest pusty
|
||||
// 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
|
||||
// wskaźnik
|
||||
Params[9].asText = new char[asNodeName.size() + 1]; // usuwane i zamieniane na wskaźnik
|
||||
strcpy(Params[9].asText, asNodeName.c_str());
|
||||
}
|
||||
parser->getTokens();
|
||||
@@ -860,17 +858,17 @@ event_manager::AddToQuery( TEvent *Event, TDynamicObject *Owner ) {
|
||||
}
|
||||
//if (DebugModeFlag)
|
||||
WriteLog(
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command ( "
|
||||
+ std::string( Event->Params[ 0 ].asText ) + " "
|
||||
+ std::to_string( Event->Params[ 1 ].asdouble ) + " "
|
||||
+ std::to_string( Event->Params[ 2 ].asdouble ) + " )" );
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command - ["
|
||||
+ std::string{ Event->Params[ 0 ].asText } + "] ["
|
||||
+ to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
|
||||
+ to_string( Event->Params[ 2 ].asdouble, 2 ) + " ]" );
|
||||
}
|
||||
//else if (DebugModeFlag)
|
||||
WriteLog(
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues ( "
|
||||
+ std::string( Event->Params[ 0 ].asText ) + " "
|
||||
+ std::to_string( Event->Params[ 1 ].asdouble ) + " "
|
||||
+ std::to_string( Event->Params[ 2 ].asdouble ) + " )" );
|
||||
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues - ["
|
||||
+ std::string( Event->Params[ 0 ].asText ) + "] ["
|
||||
+ to_string( Event->Params[ 1 ].asdouble, 2 ) + "] ["
|
||||
+ 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)
|
||||
do {
|
||||
@@ -975,13 +973,11 @@ event_manager::CheckQuery() {
|
||||
break;
|
||||
case tp_GetValues: {
|
||||
if( m_workevent->Activator ) {
|
||||
/*
|
||||
// TODO: re-enable when messaging module is in place
|
||||
if( Global::iMultiplayer ) {
|
||||
// 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->Activator->Mechanik,
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
@@ -1124,13 +1120,10 @@ event_manager::CheckQuery() {
|
||||
m_workevent->Params[ 1 ].asdouble,
|
||||
m_workevent->Params[ 2 ].asdouble );
|
||||
}
|
||||
/*
|
||||
// TODO: re-enable when messaging module is in place
|
||||
if( Global::iMultiplayer ) {
|
||||
// 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
|
||||
break;
|
||||
}
|
||||
@@ -1170,21 +1163,18 @@ event_manager::CheckQuery() {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// TODO: re-enable when messaging component is in place
|
||||
if( Global::iMultiplayer ) {
|
||||
// dajemy znać do serwera o wykonaniu
|
||||
if( ( m_workevent->iFlags & conditional_anyelse ) == 0 ) {
|
||||
// jednoznaczne tylko, gdy nie było else
|
||||
if( m_workevent->Activator ) {
|
||||
WyslijEvent( m_workevent->asName, m_workevent->Activator->name() );
|
||||
multiplayer::WyslijEvent( m_workevent->asName, m_workevent->Activator->name() );
|
||||
}
|
||||
else {
|
||||
WyslijEvent( m_workevent->asName, "" );
|
||||
multiplayer::WyslijEvent( m_workevent->asName, "" );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1273,8 +1263,8 @@ event_manager::CheckQuery() {
|
||||
+ to_string( m_workevent->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" );
|
||||
}
|
||||
else {
|
||||
// TODO: re-enable when cell manager is in place
|
||||
/*
|
||||
// TODO: re-enable when cell manager is in place
|
||||
// lista wszystkich
|
||||
for( TGroundNode *Current = nRootOfType[ TP_MEMCELL ]; Current; Current = Current->nNext ) {
|
||||
WriteLog( "Memcell \"" + Current->asName + "\": "
|
||||
|
||||
@@ -1001,13 +1001,12 @@ TDynamicObject *Global::DynamicNearest()
|
||||
{ // ustalenie pojazdu najbliższego kamerze
|
||||
return pGround->DynamicNearest(pCamera->Pos);
|
||||
};
|
||||
#endif
|
||||
|
||||
TDynamicObject *Global::CouplerNearest()
|
||||
{ // ustalenie pojazdu najbliższego kamerze
|
||||
return pGround->CouplerNearest(pCamera->Pos);
|
||||
};
|
||||
|
||||
#endif
|
||||
bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
|
||||
{
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
@@ -1016,6 +1015,7 @@ bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
|
||||
return simulation::Events.AddToQuery( event, who );
|
||||
#endif
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool Global::DoEvents()
|
||||
|
||||
@@ -299,8 +299,8 @@ class Global
|
||||
static std::string GetNextSymbol();
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
static TDynamicObject * DynamicNearest();
|
||||
#endif
|
||||
static TDynamicObject * CouplerNearest();
|
||||
#endif
|
||||
static bool AddToQuery(TEvent *event, TDynamicObject *who);
|
||||
static bool DoEvents();
|
||||
static std::string Bezogonkow(std::string str, bool _ = false);
|
||||
|
||||
31
Ground.cpp
31
Ground.cpp
@@ -243,7 +243,9 @@ void TSubRect::NodeAdd(TGroundNode *Node)
|
||||
break;
|
||||
case TP_TRACK: // TODO: tory z cieniem (tunel, canyon) też dać bez łączenia?
|
||||
++iTracks; // jeden tor więcej
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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
|
||||
// TODO: refactor sorting as universal part of drawing process in the renderer
|
||||
Node->nNext3 = nRenderRect;
|
||||
@@ -340,6 +342,7 @@ TTrack * TSubRect::FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude)
|
||||
return NULL;
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
bool TSubRect::RaTrackAnimAdd(TTrack *t)
|
||||
{ // aktywacja animacji torów w VBO (zwrotnica, obrotnica)
|
||||
if( false == m_geometrycreated ) {
|
||||
@@ -365,6 +368,7 @@ void TSubRect::RaAnimate( unsigned int const Framestamp ) {
|
||||
|
||||
m_framestamp = Framestamp;
|
||||
};
|
||||
#endif
|
||||
|
||||
TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude)
|
||||
{ // 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 NULL;
|
||||
};
|
||||
#endif
|
||||
|
||||
void
|
||||
TGround::DynamicList(bool all)
|
||||
{ // 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("none", 6); // informacja o końcu listy
|
||||
};
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
|
||||
// wyszukiwanie obiektu o podanej nazwie i konkretnym typie
|
||||
TGroundNode *
|
||||
TGround::FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType) {
|
||||
@@ -648,7 +652,7 @@ TGround::GetRect( double x, double z ) {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
// convert tp_terrain model to a series of triangle nodes
|
||||
void
|
||||
TGround::convert_terrain( TGroundNode const *Terrain ) {
|
||||
@@ -683,7 +687,7 @@ TGround::convert_terrain( TSubModel const *Submodel ) {
|
||||
delete groundnode;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
double fTrainSetVel = 0;
|
||||
double fTrainSetDir = 0;
|
||||
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ż
|
||||
};
|
||||
#endif
|
||||
|
||||
void TGround::TrackJoin(TGroundNode *Current)
|
||||
{ // wyszukiwanie sąsiednich torów do podłączenia (wydzielone na użytek obrotnicy)
|
||||
TTrack *Track = Current->pTrack;
|
||||
@@ -2774,11 +2778,7 @@ void TGround::TrackJoin(TGroundNode *Current)
|
||||
int iConnection;
|
||||
if (!Track->CurrentPrev())
|
||||
{
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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)
|
||||
{
|
||||
case 0:
|
||||
@@ -2791,11 +2791,7 @@ void TGround::TrackJoin(TGroundNode *Current)
|
||||
}
|
||||
if (!Track->CurrentNext())
|
||||
{
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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)
|
||||
{
|
||||
case 0:
|
||||
@@ -2807,7 +2803,7 @@ void TGround::TrackJoin(TGroundNode *Current)
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
|
||||
// McZapkie-070602: wyzwalacze zdarzen
|
||||
bool TGround::InitLaunchers()
|
||||
{
|
||||
@@ -3755,7 +3751,7 @@ bool TGround::GetTraction(TDynamicObject *model)
|
||||
|
||||
return true;
|
||||
};
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -3800,6 +3796,7 @@ TDynamicObject * TGround::DynamicNearest(vector3 pPosition, double distance, boo
|
||||
}
|
||||
return dyn;
|
||||
};
|
||||
|
||||
TDynamicObject * TGround::CouplerNearest(vector3 pPosition, double distance, bool mech)
|
||||
{ // wyszukanie pojazdu, którego sprzęg jest najbliżej względem (pPosition)
|
||||
TGroundNode *node;
|
||||
@@ -3829,6 +3826,7 @@ TDynamicObject * TGround::CouplerNearest(vector3 pPosition, double distance, boo
|
||||
}
|
||||
return dyn;
|
||||
};
|
||||
#endif
|
||||
//---------------------------------------------------------------------------
|
||||
void TGround::DynamicRemove(TDynamicObject *dyn)
|
||||
{ // 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()
|
||||
{ // wysłanie informacji o wszystkich zajętych odcinkach
|
||||
TGroundNode *Current;
|
||||
@@ -3987,6 +3985,7 @@ void TGround::IsolatedBusy(const std::string t)
|
||||
}
|
||||
multiplayer::WyslijString(t, 10); // wolny
|
||||
};
|
||||
#endif
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void TGround::Silence(vector3 gdzie)
|
||||
|
||||
21
Ground.h
21
Ground.h
@@ -128,14 +128,8 @@ public:
|
||||
void InitNormals();
|
||||
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
|
||||
};
|
||||
/*
|
||||
struct bounding_area {
|
||||
|
||||
glm::vec3 center; // mid point of the rectangle
|
||||
float radius { 0.0f }; // radius of the bounding sphere
|
||||
};
|
||||
*/
|
||||
class TSubRect : /*public Resource,*/ public CMesh
|
||||
class TSubRect : public CMesh
|
||||
{ // sektor składowy kwadratu kilometrowego
|
||||
public:
|
||||
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)
|
||||
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
|
||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
|
||||
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji torów
|
||||
#endif
|
||||
void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów
|
||||
};
|
||||
|
||||
@@ -273,9 +269,6 @@ class TGround
|
||||
bool CheckQuery();
|
||||
TGroundNode * DynamicFindAny(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);
|
||||
#endif
|
||||
TGroundRect * GetRect( double x, double z );
|
||||
@@ -295,25 +288,23 @@ class TGround
|
||||
return (int)(x / fSubRectSize + fHalfTotalNumSubRects); };
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TEvent * FindEvent(const std::string &asEventName);
|
||||
#endif
|
||||
void TrackJoin(TGroundNode *Current);
|
||||
|
||||
private:
|
||||
// convert tp_terrain model to a series of triangle nodes
|
||||
void convert_terrain( TGroundNode const *Terrain );
|
||||
void convert_terrain( TSubModel const *Submodel );
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void RaTriangleDivider(TGroundNode *node);
|
||||
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
public:
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void DynamicList( bool all = false );
|
||||
void TrackBusyList();
|
||||
void IsolatedBusyList();
|
||||
void IsolatedBusy( const std::string t );
|
||||
|
||||
void RadioStop(vector3 pPosition);
|
||||
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
|
||||
TDynamicObject * CouplerNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
|
||||
#endif
|
||||
void DynamicRemove(TDynamicObject *dyn);
|
||||
void TerrainRead(std::string const &f);
|
||||
void TerrainWrite();
|
||||
|
||||
10
MemCell.cpp
10
MemCell.cpp
@@ -176,8 +176,14 @@ void TMemCell::StopCommandSent()
|
||||
if (!bCommand)
|
||||
return;
|
||||
bCommand = false;
|
||||
if (OnSent) // jeśli jest event
|
||||
Global::AddToQuery(OnSent, NULL);
|
||||
if( OnSent ) {
|
||||
// jeśli jest event
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Global::AddToQuery( OnSent, NULL );
|
||||
#else
|
||||
simulation::Events.AddToQuery( OnSent, nullptr );
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
void TMemCell::AssignEvents(TEvent *e)
|
||||
|
||||
49
Model3d.cpp
49
Model3d.cpp
@@ -19,7 +19,9 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
||||
#include "logs.h"
|
||||
#include "mczapkie/mctools.h"
|
||||
#include "Usefull.h"
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
#include "ground.h"
|
||||
#endif
|
||||
#include "renderer.h"
|
||||
#include "Timer.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
|
||||
// (the offsets are part of legacy system which we now need to work around for backward compatibility)
|
||||
|
||||
if( Child )
|
||||
Child->create_geometry( Dataoffset, Bank );
|
||||
|
||||
if( false == Vertices.empty() ) {
|
||||
|
||||
tVboPtr = static_cast<int>( Dataoffset );
|
||||
Dataoffset += Vertices.size();
|
||||
// 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 );
|
||||
}
|
||||
|
||||
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 )
|
||||
Next->create_geometry( Dataoffset, Bank );
|
||||
}
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
// places contained geometry in provided ground node
|
||||
void
|
||||
TSubModel::convert( TGroundNode &Groundnode ) const {
|
||||
@@ -1063,7 +1084,7 @@ TSubModel::convert( TGroundNode &Groundnode ) const {
|
||||
Groundnode.fSquareRadius += squareradius;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void TSubModel::ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular )
|
||||
{ // ustawienie kolorów dla modelu terenu
|
||||
f4Ambient = glm::vec4( Ambient, 1.0f );
|
||||
@@ -1759,18 +1780,11 @@ void TModel3d::Init()
|
||||
return; // operacje zostały już wykonane
|
||||
if (Root)
|
||||
{
|
||||
if (iFlags & 0x0200) // jeśli wczytano z pliku tekstowego
|
||||
{ // jest jakiś dziwny błąd, że obkręcany ma być tylko ostatni submodel
|
||||
// głównego łańcucha
|
||||
// TSubModel *p=Root;
|
||||
// do
|
||||
//{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
|
||||
if (iFlags & 0x0200) {
|
||||
// jeśli wczytano z pliku tekstowego jest jakiś dziwny błąd,
|
||||
// że obkręcany ma być tylko ostatni submodel głównego łańcucha
|
||||
// argumet określa, czy wykonać pierwotny obrót
|
||||
Root->InitialRotate(true);
|
||||
}
|
||||
iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu
|
||||
if (iNumVerts) {
|
||||
@@ -1788,11 +1802,6 @@ void TModel3d::Init()
|
||||
}
|
||||
};
|
||||
|
||||
void TModel3d::BreakHierarhy()
|
||||
{
|
||||
Error("Not implemented yet :(");
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 2012-02 funkcje do tworzenia terenu z E3D
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
22
Model3d.h
22
Model3d.h
@@ -50,7 +50,12 @@ enum TAnimType // rodzaj animacji
|
||||
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
class TGroundNode;
|
||||
#endif
|
||||
namespace scene {
|
||||
class shape_node;
|
||||
}
|
||||
|
||||
class TSubModel
|
||||
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
|
||||
@@ -59,6 +64,7 @@ class TSubModel
|
||||
friend class opengl_renderer;
|
||||
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
||||
friend class TDynamicObject; // temporary etc
|
||||
friend class scene::shape_node; // temporary etc
|
||||
|
||||
public:
|
||||
enum normalization {
|
||||
@@ -131,10 +137,8 @@ private:
|
||||
|
||||
public: // chwilowo
|
||||
float3 v_TransVector { 0.0f, 0.0f, 0.0f };
|
||||
/*
|
||||
basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
|
||||
*/
|
||||
vertex_array Vertices;
|
||||
float m_boundingradius { 0 };
|
||||
size_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację
|
||||
TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane
|
||||
public:
|
||||
@@ -163,9 +167,6 @@ public:
|
||||
TSubModel * NextGet() { return Next; };
|
||||
TSubModel * ChildGet() { return Child; };
|
||||
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 SetRotateXYZ(vector3 vNewAngles);
|
||||
void SetRotateXYZ(float3 vNewAngles);
|
||||
@@ -215,8 +216,9 @@ public:
|
||||
std::vector<float4x4>&);
|
||||
void serialize_geometry( std::ostream &Output ) const;
|
||||
// places contained geometry in provided ground node
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void convert( TGroundNode &Groundnode ) const;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
class TModel3d : public CMesh
|
||||
@@ -236,6 +238,11 @@ private:
|
||||
std::string asBinary; // nazwa pod którą zapisać model binarny
|
||||
std::string m_filename;
|
||||
public:
|
||||
float bounding_radius() const {
|
||||
return (
|
||||
Root ?
|
||||
Root->m_boundingradius :
|
||||
0.f ); }
|
||||
inline TSubModel * GetSMRoot() { return (Root); };
|
||||
TModel3d();
|
||||
~TModel3d();
|
||||
@@ -246,7 +253,6 @@ public:
|
||||
void LoadFromBinFile(std::string const &FileName, bool dynamic);
|
||||
bool LoadFromFile(std::string const &FileName, bool dynamic);
|
||||
void SaveToBinFile(std::string const &FileName);
|
||||
void BreakHierarhy();
|
||||
int Flags() const { return iFlags; };
|
||||
void Init();
|
||||
std::string NameGet() { return m_filename; };
|
||||
|
||||
105
Track.cpp
105
Track.cpp
@@ -84,16 +84,14 @@ TIsolated::TIsolated(std::string const &n, TIsolated *i) :
|
||||
// utworznie obwodu izolowanego. nothing to do here.
|
||||
};
|
||||
|
||||
// TODO: put this in the cleanup routine on exit
|
||||
/*
|
||||
TIsolated *p=pRoot;
|
||||
while (pRoot)
|
||||
{
|
||||
p=pRoot;
|
||||
p->pNext=NULL;
|
||||
delete p;
|
||||
}
|
||||
*/
|
||||
void TIsolated::DeleteAll() {
|
||||
|
||||
while( pRoot ) {
|
||||
auto *next = pRoot->Next();
|
||||
delete pRoot;
|
||||
pRoot = next;
|
||||
}
|
||||
}
|
||||
|
||||
TIsolated * TIsolated::Find(std::string const &n)
|
||||
{ // znalezienie obiektu albo utworzenie nowego
|
||||
@@ -1065,7 +1063,11 @@ bool TTrack::InMovement()
|
||||
return false;
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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
|
||||
if (eType == tt_Table)
|
||||
{
|
||||
@@ -2259,7 +2261,7 @@ bool TTrack::Switch(int i, float const t, float const d)
|
||||
}
|
||||
else if (eType == tt_Table)
|
||||
{ // 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
|
||||
if (trPrev) // jeśli jest tor od Point1 obrotnicy
|
||||
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ę!
|
||||
if (SwitchExtension->pOwner)
|
||||
SwitchExtension->pOwner->RaTrackAnimAdd(this); // dodanie do listy animacyjnej
|
||||
// TODO: unregister path ends in the owner cell
|
||||
}
|
||||
else
|
||||
{ // 1: ustalenie finalnego położenia (gdy nie było animacji)
|
||||
RaAnimate(); // ostatni etap animowania
|
||||
// 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);
|
||||
#else
|
||||
simulation::Region->TrackJoin( this );
|
||||
#endif
|
||||
if (trNext || trPrev)
|
||||
{
|
||||
fVelocity = 6.0; // jazda dozwolona
|
||||
if (trPrev)
|
||||
if (trPrev->fVelocity ==
|
||||
0.0) // ustawienie 0 da możliwość zatrzymania AI na obrotnicy
|
||||
trPrev->VelocitySet(6.0); // odblokowanie dołączonego toru do jazdy
|
||||
if (trNext)
|
||||
if (trNext->fVelocity == 0.0)
|
||||
trNext->VelocitySet(6.0);
|
||||
if (SwitchExtension->evPlus) // w starych sceneriach może nie być
|
||||
Global::AddToQuery(SwitchExtension->evPlus,
|
||||
NULL); // potwierdzenie wykonania (np. odpala WZ)
|
||||
if( ( trPrev )
|
||||
&& ( trPrev->fVelocity == 0.0 ) ) {
|
||||
// ustawienie 0 da możliwość zatrzymania AI na obrotnicy
|
||||
trPrev->VelocitySet( 6.0 ); // odblokowanie dołączonego toru do jazdy
|
||||
}
|
||||
if( ( trNext )
|
||||
&& ( trNext->fVelocity == 0.0 ) ) {
|
||||
trNext->VelocitySet( 6.0 );
|
||||
}
|
||||
if( SwitchExtension->evPlus ) { // w starych sceneriach może nie być
|
||||
// potwierdzenie wykonania (np. odpala WZ)
|
||||
Global::AddToQuery( SwitchExtension->evPlus, nullptr );
|
||||
}
|
||||
}
|
||||
}
|
||||
SwitchExtension->CurrentIndex = i; // zapamiętanie stanu zablokowania
|
||||
@@ -2528,7 +2539,11 @@ TTrack * TTrack::RaAnimate()
|
||||
cosa = -hlen * std::cos(glm::radians(SwitchExtension->fOffset));
|
||||
SwitchExtension->vTrans = ac->TransGet();
|
||||
vector3 middle =
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
SwitchExtension->pMyNode->pCenter +
|
||||
#else
|
||||
SwitchExtension->pMyNode->area().center +
|
||||
#endif
|
||||
SwitchExtension->vTrans; // SwitchExtension->Segments[0]->FastGetPoint(0.5);
|
||||
Segment->Init(middle + vector3(sina, 0.0, cosa),
|
||||
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
|
||||
void
|
||||
path_table::InitTracks() {
|
||||
@@ -2957,3 +2977,46 @@ path_table::InitTracks() {
|
||||
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
34
Track.h
@@ -13,11 +13,15 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
#include "scenenode.h"
|
||||
#include "Segment.h"
|
||||
#include "material.h"
|
||||
#include "scenenode.h"
|
||||
#include "names.h"
|
||||
|
||||
namespace scene {
|
||||
class basic_cell;
|
||||
}
|
||||
|
||||
enum TTrackType {
|
||||
tt_Unknown,
|
||||
tt_Normal,
|
||||
@@ -71,7 +75,11 @@ class TSwitchExtension
|
||||
};
|
||||
struct
|
||||
{ // zmienne potrzebne tylko dla obrotnicy/przesuwnicy
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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
|
||||
TAnimModel *pModel; // na razie model
|
||||
};
|
||||
@@ -83,7 +91,11 @@ class TSwitchExtension
|
||||
};
|
||||
};
|
||||
bool bMovement = false; // czy w trakcie animacji
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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
|
||||
TEvent *evPlus = nullptr,
|
||||
*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
|
||||
TIsolated();
|
||||
TIsolated(const std::string &n, TIsolated *i);
|
||||
static void DeleteAll();
|
||||
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
|
||||
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
|
||||
bool Busy() {
|
||||
@@ -245,11 +258,20 @@ public:
|
||||
#endif
|
||||
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) {
|
||||
if (SwitchExtension)
|
||||
SwitchExtension->pOwner = o; };
|
||||
#else
|
||||
void RaOwnerSet( scene::basic_cell *o ) {
|
||||
if( SwitchExtension ) { SwitchExtension->pOwner = o; } };
|
||||
#endif
|
||||
bool InMovement(); // czy w trakcie animacji?
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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);
|
||||
TTrack * RaAnimate();
|
||||
|
||||
@@ -278,9 +300,19 @@ public:
|
||||
class path_table : public basic_table<TTrack> {
|
||||
|
||||
public:
|
||||
~path_table();
|
||||
// legacy method, initializes tracks after deserialization from scenario file
|
||||
void
|
||||
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;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
78
World.cpp
78
World.cpp
@@ -318,6 +318,8 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
Controlled = NULL;
|
||||
mvControlled = NULL;
|
||||
Camera.Type = tp_Free;
|
||||
DebugCamera = Camera;
|
||||
Global::DebugCameraPosition = DebugCamera.Pos;
|
||||
}
|
||||
|
||||
// if (!Global::bMultiplayer) //na razie włączone
|
||||
@@ -543,7 +545,7 @@ void TWorld::OnKeyDown(int cKey)
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *tmp = Ground.DynamicNearest( Camera.Pos, 50, true ); //łapiemy z obsadą
|
||||
#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
|
||||
if( ( tmp != nullptr )
|
||||
&& ( tmp != Controlled ) ) {
|
||||
@@ -688,8 +690,12 @@ void TWorld::OnKeyDown(int cKey)
|
||||
}
|
||||
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
|
||||
if (Controlled->MoverParameters->Radio)
|
||||
Ground.RadioStop(Camera.Pos);
|
||||
if( Controlled->MoverParameters->Radio )
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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
|
||||
if (Train)
|
||||
@@ -725,7 +731,7 @@ void TWorld::OnKeyDown(int cKey)
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *temp = Global::DynamicNearest();
|
||||
#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
|
||||
if (temp)
|
||||
{
|
||||
@@ -739,7 +745,11 @@ void TWorld::OnKeyDown(int cKey)
|
||||
}
|
||||
else if (cKey == Global::Keys[k_EndSign])
|
||||
{ // Ra 2014-07: zabrane z kabiny
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
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)
|
||||
{
|
||||
int CouplNr = (LengthSquared3(tmp->HeadPosition() - Camera.Pos) >
|
||||
@@ -772,7 +782,7 @@ void TWorld::OnKeyDown(int cKey)
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *temp = Global::DynamicNearest();
|
||||
#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
|
||||
if (temp)
|
||||
{
|
||||
@@ -795,7 +805,7 @@ void TWorld::OnKeyDown(int cKey)
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *temp = Global::DynamicNearest();
|
||||
#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
|
||||
if (temp)
|
||||
{
|
||||
@@ -835,6 +845,8 @@ void TWorld::InOutKey( bool const Near )
|
||||
Train->Dynamic()->bDisplayCab = false;
|
||||
DistantView( Near );
|
||||
}
|
||||
DebugCamera = Camera;
|
||||
Global::DebugCameraPosition = DebugCamera.Pos;
|
||||
}
|
||||
else
|
||||
{ // jazda w kabinie
|
||||
@@ -1172,9 +1184,9 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
if( !d )
|
||||
d = Ground.DynamicNearest( Camera.Pos, 1000 ); // dalej szukanie, jesli bliżej nie ma
|
||||
#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 )
|
||||
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
|
||||
if( d && pDynamicNearest ) {
|
||||
// jeśli jakiś jest znaleziony wcześniej
|
||||
@@ -1361,7 +1373,7 @@ TWorld::Update_UI() {
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.DynamicNearest( Camera.Pos ) :
|
||||
#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
|
||||
Controlled ); // w trybie latania lokalizujemy wg mapy
|
||||
|
||||
@@ -1446,7 +1458,7 @@ TWorld::Update_UI() {
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.DynamicNearest( Camera.Pos ) :
|
||||
#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
|
||||
Controlled ); // w trybie latania lokalizujemy wg mapy
|
||||
|
||||
@@ -1714,7 +1726,7 @@ TWorld::Update_UI() {
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.DynamicNearest( Camera.Pos ) :
|
||||
#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
|
||||
Controlled ); // w trybie latania lokalizujemy wg mapy
|
||||
if( tmp == nullptr ) {
|
||||
@@ -1908,7 +1920,6 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) + " rcvd" );
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
if( Global::iMultiplayer ) {
|
||||
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
|
||||
TEvent *e = Ground.FindEvent(
|
||||
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||
if( e )
|
||||
@@ -1918,7 +1929,6 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
}
|
||||
#else
|
||||
if( Global::iMultiplayer ) {
|
||||
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
|
||||
auto *event = simulation::Events.FindEvent( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||
if( event != nullptr ) {
|
||||
if( ( event->Type == tp_Multiple )
|
||||
@@ -2027,7 +2037,6 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
if (t)
|
||||
multiplayer::WyslijNamiary(t); // wysłanie informacji o pojeździe
|
||||
#else
|
||||
/*
|
||||
// TODO: re-enable when messaging component is in place
|
||||
auto *vehicle = (
|
||||
pRozkaz->cString[ 1 ] == '*' ?
|
||||
@@ -2036,27 +2045,42 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
if( vehicle != nullptr ) {
|
||||
multiplayer::WyslijNamiary( vehicle ); // wysłanie informacji o pojeździe
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// 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();
|
||||
#else
|
||||
simulation::Vehicles.DynamicList();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8: // ponowne wysłanie informacji o zajętych odcinkach toru
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy track" + " rcvd");
|
||||
Ground.TrackBusyList();
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.TrackBusyList();
|
||||
#else
|
||||
simulation::Paths.TrackBusyList();
|
||||
#endif
|
||||
break;
|
||||
case 9: // ponowne wysłanie informacji o zajętych odcinkach izolowanych
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " all busy isolated" + " rcvd");
|
||||
Ground.IsolatedBusyList();
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.IsolatedBusyList();
|
||||
#else
|
||||
simulation::Paths.IsolatedBusyList();
|
||||
#endif
|
||||
break;
|
||||
case 10: // badanie zajętości jednego odcinka izolowanego
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
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])));
|
||||
#else
|
||||
simulation::Paths.IsolatedBusy( std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||
#endif
|
||||
break;
|
||||
case 11: // ustawienie parametrów ruchu pojazdu
|
||||
// Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0])));
|
||||
@@ -2096,7 +2120,25 @@ void TWorld::OnCommandGet(multiplayer::DaneRozkaz *pRozkaz)
|
||||
}
|
||||
}
|
||||
#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
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ WyslijWolny(const std::string &t)
|
||||
WyslijString(t, 4); // tor wolny
|
||||
}
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void
|
||||
WyslijNamiary(TGroundNode *t)
|
||||
{ // 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!");
|
||||
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
|
||||
WyslijObsadzone()
|
||||
|
||||
@@ -11,7 +11,11 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
class TGroundNode;
|
||||
#else
|
||||
class TDynamicObject;
|
||||
#endif
|
||||
|
||||
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 WyslijString( const std::string &t, int n );
|
||||
void WyslijWolny( const std::string &t );
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void WyslijNamiary( TGroundNode *t );
|
||||
#else
|
||||
void WyslijNamiary( TDynamicObject const *Vehicle );
|
||||
#endif
|
||||
void WyslijParam( int nr, int fl );
|
||||
void WyslijUszkodzenia( const std::string &t, char fl );
|
||||
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
||||
|
||||
109
renderer.cpp
109
renderer.cpp
@@ -349,6 +349,15 @@ opengl_renderer::Render() {
|
||||
void
|
||||
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 );
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
|
||||
@@ -365,14 +374,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
#endif
|
||||
shadowcamera = m_renderpass.camera; // cache shadow camera placement for visualization
|
||||
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
|
||||
m_shadowtexturematrix =
|
||||
//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::vec3{ m_renderpass.camera.position() - shadowcamera.position() } );
|
||||
}
|
||||
|
||||
if( ( true == m_environmentcubetexturesupport )
|
||||
&& ( true == World.InitPerformed() ) ) {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
::glViewport( 0, 0, Global::iWindowWidth, Global::iWindowHeight );
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
@@ -420,7 +419,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
::glColor4f( 1.f, 0.9f, 0.8f, 1.f );
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
shadowcamera.draw( m_renderpass.camera.position() - shadowcamera.position() );
|
||||
if( true == Global::RenderShadows ) {
|
||||
shadowcamera.draw( m_renderpass.camera.position() - shadowcamera.position() );
|
||||
}
|
||||
if( DebugCameraFlag ) {
|
||||
::glColor4f( 0.8f, 1.f, 0.9f, 1.f );
|
||||
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
|
||||
#ifdef EU07_USE_DEBUG_CULLING
|
||||
// debug
|
||||
float const width = scene::EU07_SECTIONSIZE * 0.5f;
|
||||
float const width = section->m_area.radius;
|
||||
float const height = scene::EU07_SECTIONSIZE * 0.2f;
|
||||
glDisable( GL_LIGHTING );
|
||||
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
|
||||
while( First != Last ) {
|
||||
|
||||
auto const *cell = First->second;
|
||||
/*
|
||||
// przeliczenia animacji torów w sektorze
|
||||
Groundsubcell->RaAnimate( m_framestamp );
|
||||
*/
|
||||
auto *cell = First->second;
|
||||
// przeliczenia animacji torów w sektorze
|
||||
cell->RaAnimate( m_framestamp );
|
||||
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color: {
|
||||
// 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
|
||||
#ifdef EU07_USE_DEBUG_CULLING
|
||||
// debug
|
||||
float const width = scene::EU07_CELLSIZE * 0.5f;
|
||||
float const width = cell->m_area.radius;
|
||||
float const height = scene::EU07_CELLSIZE * 0.15f;
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
@@ -2149,25 +2149,8 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
||||
|
||||
void
|
||||
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 ) {
|
||||
double distancesquared;
|
||||
@@ -3075,8 +3058,8 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
|
||||
// render
|
||||
m_geometry.draw( Node->Piece->geometry );
|
||||
// ++m_debugstats.lines;
|
||||
// ++m_debugstats.drawcalls;
|
||||
++m_debugstats.lines;
|
||||
++m_debugstats.drawcalls;
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
@@ -3183,8 +3166,9 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque
|
||||
while( first != Last ) {
|
||||
|
||||
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
|
||||
::glPushMatrix();
|
||||
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 );
|
||||
// render
|
||||
for( auto *traction : cell->m_traction ) { Render_Alpha( traction ); }
|
||||
for( auto &lines : cell->m_lines ) { Render_Alpha( lines ); }
|
||||
// post-render cleanup
|
||||
::glLineWidth( 1.0 );
|
||||
if( !Global::bSmoothTraction ) {
|
||||
@@ -3287,6 +3272,48 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
|
||||
++m_debugstats.traction;
|
||||
++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
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
|
||||
@@ -340,6 +340,8 @@ private:
|
||||
Render_Alpha( TAnimModel *Instance );
|
||||
void
|
||||
Render_Alpha( TTraction *Traction );
|
||||
void
|
||||
Render_Alpha( scene::lines_node const &Lines );
|
||||
#endif
|
||||
bool
|
||||
Render_Alpha( TDynamicObject *Dynamic );
|
||||
|
||||
298
scene.cpp
298
scene.cpp
@@ -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
|
||||
void
|
||||
basic_cell::insert( shape_node Shape ) {
|
||||
@@ -160,15 +198,51 @@ basic_cell::insert( shape_node 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
|
||||
void
|
||||
basic_cell::insert( TTrack *Path ) {
|
||||
|
||||
m_active = true;
|
||||
|
||||
// TODO: add animation hook
|
||||
Path->origin( m_area.center );
|
||||
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
|
||||
@@ -179,6 +253,13 @@ basic_cell::insert( TTraction *Traction ) {
|
||||
|
||||
Traction->origin( m_area.center );
|
||||
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
|
||||
@@ -203,6 +284,15 @@ basic_cell::insert( TAnimModel *Instance ) {
|
||||
// opaque pieces
|
||||
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
|
||||
@@ -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
|
||||
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 };
|
||||
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 ) ) {
|
||||
continue;
|
||||
}
|
||||
distance = glm::length2( glm::dvec3{ vehicle->GetPosition() } - Point );
|
||||
if( false == Findbycoupler ) {
|
||||
// basic search, checks vehicles' center points
|
||||
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 )
|
||||
|| ( distance > leastdistance ) ){
|
||||
continue;
|
||||
@@ -372,10 +471,13 @@ basic_cell::create_geometry( geometrybank_handle const &Bank ) {
|
||||
for( auto *path : m_paths ) { path->create_geometry( Bank ); }
|
||||
for( auto *traction : m_traction ) { traction->create_geometry( Bank ); }
|
||||
#endif
|
||||
for( auto &lines : m_lines ) { lines.create_geometry( Bank ); }
|
||||
// arrange content by assigned materials to minimize state switching
|
||||
std::sort(
|
||||
std::begin( m_paths ), std::end( m_paths ),
|
||||
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
|
||||
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 ) {
|
||||
|
||||
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
|
||||
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 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 ) {
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
void
|
||||
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
|
||||
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
|
||||
TDynamicObject
|
||||
@@ -456,14 +575,12 @@ basic_section::find( glm::dvec3 const &Point, float const Radius, bool const Onl
|
||||
distancefound,
|
||||
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 ) {
|
||||
// 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;
|
||||
}
|
||||
std::tie( vehiclefound, distancefound ) = cell.find( Point, Radius, Onlycontrolled );
|
||||
std::tie( vehiclefound, distancefound ) = cell.find( Point, Radius, Onlycontrolled, Findbycoupler );
|
||||
if( ( vehiclefound != nullptr )
|
||||
&& ( distancefound < distancenearest ) ) {
|
||||
|
||||
@@ -503,11 +620,10 @@ basic_section::find( glm::dvec3 const &Point, TTraction const *Other, int const
|
||||
endpointnearest { -1 };
|
||||
|
||||
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 ) {
|
||||
// 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;
|
||||
}
|
||||
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
|
||||
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 §ionlist = 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
|
||||
// using deque so we can do single pass iterating and addding generated pieces without invalidating anything
|
||||
@@ -628,38 +785,41 @@ basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) {
|
||||
if( shape.m_data.vertices.empty() ) { return; }
|
||||
|
||||
// adjust input if necessary:
|
||||
if( Scratchpad.location_rotation != glm::vec3( 0, 0, 0 ) ) {
|
||||
// rotate...
|
||||
auto const rotation = glm::radians( Scratchpad.location_rotation );
|
||||
for( auto &vertex : shape.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 );
|
||||
vertex.normal = glm::rotateZ( vertex.normal, rotation.z );
|
||||
vertex.normal = glm::rotateX( vertex.normal, rotation.x );
|
||||
vertex.normal = glm::rotateY( vertex.normal, rotation.y );
|
||||
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 ) ) {
|
||||
// rotate...
|
||||
auto const rotation = glm::radians( Scratchpad.location_rotation );
|
||||
for( auto &vertex : shape.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 );
|
||||
vertex.normal = glm::rotateZ( vertex.normal, rotation.z );
|
||||
vertex.normal = glm::rotateX( vertex.normal, rotation.x );
|
||||
vertex.normal = glm::rotateY( vertex.normal, 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 : shape.m_data.vertices ) {
|
||||
vertex.position += offset;
|
||||
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 : shape.m_data.vertices ) {
|
||||
vertex.position += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
// calculate bounding area
|
||||
for( auto const &vertex : shape.m_data.vertices ) {
|
||||
shape.m_data.area.center += vertex.position;
|
||||
}
|
||||
shape.m_data.area.center /= shape.m_data.vertices.size();
|
||||
// trim the shape if needed. trimmed parts will be added to list as separate nodes
|
||||
for( std::size_t index = 0; index < shapes.size(); ++index ) {
|
||||
while( true == RaTriangleDivider( shapes[ index ], shapes ) ) {
|
||||
; // all work is done during expression check
|
||||
// calculate bounding area
|
||||
for( auto const &vertex : shape.m_data.vertices ) {
|
||||
shape.m_data.area.center += vertex.position;
|
||||
}
|
||||
shape.m_data.area.center /= shape.m_data.vertices.size();
|
||||
// trim the shape if needed. trimmed parts will be added to list as separate nodes
|
||||
for( std::size_t index = 0; index < shapes.size(); ++index ) {
|
||||
while( true == RaTriangleDivider( shapes[ index ], shapes ) ) {
|
||||
; // all work is done during expression check
|
||||
}
|
||||
// with the trimming done we can calculate shape's bounding radius
|
||||
shape.compute_radius();
|
||||
}
|
||||
// with the trimming done we can calculate shape's bounding radius
|
||||
shape.compute_radius();
|
||||
}
|
||||
// move the data into appropriate section(s)
|
||||
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
|
||||
void
|
||||
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
|
||||
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 §ionlist = sections( Point, Radius );
|
||||
// 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() };
|
||||
|
||||
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 )
|
||||
&& ( founddistance < nearestdistance ) ) {
|
||||
|
||||
|
||||
58
scene.h
58
scene.h
@@ -61,9 +61,21 @@ public:
|
||||
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||
void
|
||||
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
|
||||
void
|
||||
insert( shape_node Shape );
|
||||
// adds provided lines to the cell
|
||||
void
|
||||
insert( lines_node Lines );
|
||||
// adds provided path to the cell
|
||||
void
|
||||
insert( TTrack *Path );
|
||||
@@ -85,9 +97,9 @@ public:
|
||||
// registers provided traction piece in the lookup directory of the cell
|
||||
void
|
||||
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>
|
||||
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
|
||||
std::tuple<TTrack *, int>
|
||||
find( glm::dvec3 const &Point, TTrack const *Exclude );
|
||||
@@ -111,19 +123,19 @@ public:
|
||||
private:
|
||||
// types
|
||||
using shapenode_sequence = std::vector<shape_node>;
|
||||
using linesnode_sequence = std::vector<lines_node>;
|
||||
using path_sequence = std::vector<TTrack *>;
|
||||
// using path_set = std::unordered_set<TTrack *>;
|
||||
using traction_sequence = std::vector<TTraction *>;
|
||||
// using traction_set = std::unordered_set<TTraction *>;
|
||||
using instance_sequence = std::vector<TAnimModel *>;
|
||||
using sound_sequence = std::vector<TTextSound *>;
|
||||
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
||||
// 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
|
||||
// content
|
||||
shapenode_sequence m_shapesopaque; // opaque pieces of geometry
|
||||
shapenode_sequence m_shapestranslucent; // translucent pieces of geometry
|
||||
linesnode_sequence m_lines;
|
||||
path_sequence m_paths; // path pieces
|
||||
instance_sequence m_instancesopaque;
|
||||
instance_sequence m_instancetranslucent;
|
||||
@@ -135,6 +147,10 @@ private:
|
||||
path_sequence paths;
|
||||
traction_sequence traction;
|
||||
} 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
|
||||
@@ -150,22 +166,33 @@ public:
|
||||
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||
void
|
||||
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
|
||||
void
|
||||
insert( shape_node Shape );
|
||||
// adds provided lines to the section
|
||||
void
|
||||
insert( lines_node Lines );
|
||||
// adds provided node to the section
|
||||
template <class Type_>
|
||||
void
|
||||
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
|
||||
template <class Type_>
|
||||
void
|
||||
register_node( Type_ *Node, glm::dvec3 const &Point ) {
|
||||
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>
|
||||
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
|
||||
std::tuple<TTrack *, int>
|
||||
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
|
||||
void
|
||||
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
|
||||
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
|
||||
void
|
||||
insert_path( TTrack *Path, scratch_data &Scratchpad );
|
||||
@@ -241,9 +277,9 @@ public:
|
||||
// inserts provided event launcher in the region
|
||||
void
|
||||
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>
|
||||
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
|
||||
std::tuple<TTrack *, int>
|
||||
find_path( glm::dvec3 const &Point, TTrack const *Exclude );
|
||||
|
||||
206
scenenode.cpp
206
scenenode.cpp
@@ -207,6 +207,65 @@ shape_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
||||
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
|
||||
bool
|
||||
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::deserialize( cParser &Input, node_data const &Nodedata ) {
|
||||
@@ -279,6 +483,8 @@ memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
|
||||
*/
|
||||
} // scene
|
||||
|
||||
|
||||
|
||||
namespace editor {
|
||||
|
||||
basic_node::basic_node( scene::node_data const &Nodedata ) :
|
||||
|
||||
57
scenenode.h
57
scenenode.h
@@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "vertex.h"
|
||||
#include "openglgeometrybank.h"
|
||||
#include "parser.h"
|
||||
#include "model3d.h"
|
||||
|
||||
struct lighting_data {
|
||||
|
||||
@@ -104,6 +105,9 @@ public:
|
||||
// restores content of the node from provded input stream
|
||||
shape_node &
|
||||
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
|
||||
bool
|
||||
merge( shape_node &Shape );
|
||||
@@ -132,6 +136,59 @@ private:
|
||||
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
|
||||
|
||||
@@ -352,7 +352,29 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
|
||||
if( nodedata.range_min < 0.0 ) {
|
||||
// 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 {
|
||||
// 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_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" )
|
||||
|| ( nodedata.type == "line_strip" )
|
||||
|| ( nodedata.type == "line_loop" ) ) {
|
||||
|
||||
// TODO: implement
|
||||
skip_until( Input, "endline" );
|
||||
simulation::Region->insert_lines(
|
||||
scene::lines_node().deserialize(
|
||||
Input, nodedata ),
|
||||
Scratchpad );
|
||||
}
|
||||
else if( nodedata.type == "memcell" ) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user