build 1020: error fixes and backward compatibility improvements

This commit is contained in:
tmj-fstate
2017-10-22 19:19:16 +02:00
parent 87348a2ab8
commit 7ad760821f
17 changed files with 369 additions and 149 deletions

View File

@@ -791,7 +791,7 @@ void TAnimModel::LightSet(int n, float v)
case ls_Dark: {
// zapalenie świateł zależne od oświetlenia scenerii
if( v > 3.0 ) { fDark = v - 3.0; } // ustawienie indywidualnego progu zapalania
else { fDark = 0.25; } // standardowy próg zaplania
else { fDark = DefaultDarkThresholdLevel; } // standardowy próg zaplania
break;
}
}

View File

@@ -19,6 +19,7 @@ http://mozilla.org/MPL/2.0/.
#include "DynObj.h"
const int iMaxNumLights = 8;
float const DefaultDarkThresholdLevel { 0.325f };
// typy stanu świateł
enum TLightState
@@ -174,7 +175,7 @@ private:
std::string asText; // tekst dla wyświetlacza znakowego
TAnimAdvanced *pAdvanced { nullptr };
TLightState lsLights[ iMaxNumLights ];
float fDark { 0.25f }; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
float fDark { DefaultDarkThresholdLevel }; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
float fOnTime { 0.66f };
float fOffTime { 0.66f + 0.66f }; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame

View File

@@ -1268,7 +1268,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// jeśli ma stać, dostaje komendę od razu
go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
}
else if( sSpeedTable[ i ].fDist <= 20.0 ) {
else if( sSpeedTable[ i ].fDist <= fMaxProximityDist ) {
// jeśli ma dociągnąć, to niech dociąga
// (moveStopCloser dotyczy dociągania do W4, nie semafora)
go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
@@ -2412,7 +2412,7 @@ bool TController::IncBrake()
}
case Pneumatic: {
// NOTE: can't perform just test whether connected vehicle == nullptr, due to virtual couplers formed with nearby vehicles
bool standalone{ true };
bool standalone { true };
if( ( mvOccupied->TrainType == dt_ET41 )
|| ( mvOccupied->TrainType == dt_ET42 ) ) {
// NOTE: we're doing simplified checks full of presuptions here.
@@ -2427,9 +2427,24 @@ bool TController::IncBrake()
}
}
else {
/*
standalone =
( ( mvOccupied->Couplers[ 0 ].CouplingFlag == 0 )
&& ( mvOccupied->Couplers[ 1 ].CouplingFlag == 0 ) );
*/
if( pVehicles[ 0 ] != pVehicles[ 1 ] ) {
// more detailed version, will use manual braking also for coupled sets of controlled vehicles
auto *vehicle = pVehicles[ 0 ]; // start from first
while( ( true == standalone )
&& ( vehicle != nullptr ) ) {
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
standalone =
( ( ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag & coupling::control ) )
&& ( ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag & coupling::control ) ) );
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
}
}
}
if( true == standalone ) {
OK = mvOccupied->IncLocalBrakeLevel(
@@ -2986,8 +3001,7 @@ void TController::RecognizeCommand()
}
void TController::PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation, TStopReason reason)
{ // wysłanie komendy przez event PutValues, jak pojazd ma obsadę, to wysyła tutaj, a nie do pojazdu
// bezpośrednio
{ // wysłanie komendy przez event PutValues, jak pojazd ma obsadę, to wysyła tutaj, a nie do pojazdu bezpośrednio
#ifdef EU07_USE_OLD_GROUNDCODE
vector3 sl;
sl.x = -NewLocation.X; // zamiana na współrzędne scenerii
@@ -2995,7 +3009,7 @@ void TController::PutCommand(std::string NewCommand, double NewValue1, double Ne
sl.y = NewLocation.Z;
#else
// zamiana na współrzędne scenerii
glm::dvec3 sl { -NewLocation.X, NewLocation.Y, NewLocation.Z };
glm::dvec3 sl { -NewLocation.X, NewLocation.Z, NewLocation.Y };
#endif
if (!PutCommand(NewCommand, NewValue1, NewValue2, &sl, reason))
mvOccupied->PutCommand(NewCommand, NewValue1, NewValue2, NewLocation);
@@ -3840,8 +3854,11 @@ TController::UpdateSituation(double dt) {
CheckVehicles(); // sprawdzić światła nowego składu
JumpToNextOrder(); // wykonanie następnej komendy
}
/*
// NOTE: disabled as speed limit is decided in another place based on distance to potential target
else
SetVelocity(2.0, 0.0); // jazda w ustawionym kierunku z prędkością 2 (18s)
*/
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
}
else {
@@ -4329,7 +4346,12 @@ TController::UpdateSituation(double dt) {
if( OrderCurrentGet() & Connect ) {
// jeśli spinanie, to jechać dalej
AccPreferred = std::min( 0.25, AccPreferred ); // nie hamuj
VelDesired = Global::Min0RSpeed( 20.0, VelDesired );
VelDesired =
Global::Min0RSpeed(
VelDesired,
( vehicle->fTrackBlock > 150.0 ?
20.0:
4.0 ) );
VelNext = 2.0; // i pakuj się na tamtego
}
else {
@@ -4372,7 +4394,12 @@ TController::UpdateSituation(double dt) {
else {
if( OrderCurrentGet() & Connect ) {
// if there's something nearby in the connect mode don't speed up too much
VelDesired = Global::Min0RSpeed( 20.0, VelDesired );
VelDesired =
Global::Min0RSpeed(
VelDesired,
( vehicle->fTrackBlock > 150.0 ?
20.0 :
4.0 ) );
}
}
}

View File

@@ -25,7 +25,6 @@ http://mozilla.org/MPL/2.0/.
#include "AirCoupler.h"
#include "TractionPower.h"
#include "Ground.h" //bo Global::pGround->bDynamicRemove
#include "Event.h"
#include "Driver.h"
#include "Camera.h" //bo likwidujemy trzęsienie
@@ -49,6 +48,7 @@ std::string const TDynamicObject::MED_labels[] = {
"masa: ", "amax: ", "Fzad: ", "FmPN: ", "FmED: ", "FrED: ", "FzPN: ", "nPrF: "
};
bool TDynamicObject::bDynamicRemove { false };
//---------------------------------------------------------------------------
void TAnimPant::AKP_4E()
@@ -2922,7 +2922,7 @@ bool TDynamicObject::Update(double dt, double dt1)
Move(dDOMoveLen);
if (!bEnabled) // usuwane pojazdy nie mają toru
{ // pojazd do usunięcia
Global::pGround->bDynamicRemove = true; // sprawdzić
bDynamicRemove = true; // sprawdzić
return false;
}
Global::ABuDebug = dDOMoveLen / dt1;
@@ -5364,6 +5364,7 @@ vehicle_table::update( double Deltatime, int Iterationcount ) {
// pojazdy stojące nie potrzebują aktualizacji, chyba że np. ktoś im zmieni nastawę hamulca
// oddzielną listę można by zrobić na pojazdy z napędem, najlepiej posortowaną wg typu napędu
for( auto *vehicle : m_items ) {
if( false == vehicle->bEnabled ) { continue; }
// Ra: zmienić warunek na sprawdzanie pantografów w jednej zmiennej: czy pantografy i czy podniesione
if( vehicle->MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) {
// TODO: re-implement
@@ -5395,7 +5396,7 @@ vehicle_table::update( double Deltatime, int Iterationcount ) {
}
/*
// TODO: re-implement
if (bDynamicRemove)
if (TDynamicObject::bDynamicRemove)
{ // jeśli jest coś do usunięcia z listy, to trzeba na końcu
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
if ( false == Current->DynamicObject->bEnabled)
@@ -5403,7 +5404,7 @@ vehicle_table::update( double Deltatime, int Iterationcount ) {
DynamicRemove(Current->DynamicObject); // usunięcie tego i podłączonych
Current = nRootDynamic; // sprawdzanie listy od początku
}
bDynamicRemove = false; // na razie koniec
TDynamicObject::bDynamicRemove = false; // na razie koniec
}
*/
}

View File

@@ -151,6 +151,9 @@ class TDynamicObject { // klasa pojazdu
friend class opengl_renderer;
public:
static bool bDynamicRemove; // moved from ground
private: // położenie pojazdu w świecie oraz parametry ruchu
Math3D::vector3 vPosition; // Ra: pozycja pojazdu liczona zaraz po przesunięciu
Math3D::vector3 vCoulpler[ 2 ]; // współrzędne sprzęgów do liczenia zderzeń czołowych

View File

@@ -435,12 +435,13 @@ void TSubRect::LoadNodes() {
node = node->nNext2; // następny z sektora
}
}
#ifdef EU07_USE_OLD_GROUNDCODE
void TSubRect::RenderSounds()
{ // aktualizacja dźwięków w pojazdach sektora (sektor może nie być wyświetlany)
for (int j = 0; j < iTracks; ++j)
tTracks[j]->RenderDynSounds(); // dźwięki pojazdów idą niezależnie od wyświetlania
};
#endif
//---------------------------------------------------------------------------
//------------------ Kwadrat kilometrowy ------------------------------------
//---------------------------------------------------------------------------
@@ -2723,7 +2724,7 @@ void TGround::InitTraction()
if (!Traction->hvParallel)
ErrorLog("Missed overhead: " + Traction->asParallel); // logowanie braku
}
if (Traction->iTries > 0) // jeśli zaznaczony do podłączenia
if (Traction->iTries == 5) // jeśli zaznaczony do podłączenia
// if (!nCurrent->hvTraction->psPower[0]||!nCurrent->hvTraction->psPower[1])
if (zg < iConnection) // zabezpieczenie
nEnds[zg++] = nCurrent; // wypełnianie tabeli końców w celu szukania im połączeń
@@ -3466,7 +3467,7 @@ bool TGround::Update(double dt, int iter)
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
Current->DynamicObject->Update(dt, dt); // Ra 2015-01: tylko tu przelicza sieć trakcyjną
}
if (bDynamicRemove)
if (TDynamicObject::bDynamicRemove)
{ // jeśli jest coś do usunięcia z listy, to trzeba na końcu
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
if ( false == Current->DynamicObject->bEnabled)
@@ -3474,7 +3475,7 @@ bool TGround::Update(double dt, int iter)
DynamicRemove(Current->DynamicObject); // usunięcie tego i podłączonych
Current = nRootDynamic; // sprawdzanie listy od początku
}
bDynamicRemove = false; // na razie koniec
TDynamicObject::bDynamicRemove = false; // na razie koniec
}
return true;
};
@@ -3985,7 +3986,6 @@ void TGround::IsolatedBusy(const std::string t)
}
multiplayer::WyslijString(t, 10); // wolny
};
#endif
//---------------------------------------------------------------------------
void TGround::Silence(vector3 gdzie)
@@ -4006,4 +4006,5 @@ void TGround::Silence(vector3 gdzie)
tmp->RenderSounds(); // dźwięki pojazdów by się przydało wyłączyć
}
};
#endif
//---------------------------------------------------------------------------

View File

@@ -162,8 +162,8 @@ class TSubRect : public CMesh
#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
#endif
};
// Ra: trzeba sprawdzić wydajność siatki
@@ -243,7 +243,6 @@ class TGround
#endif
public:
bool bDynamicRemove = false; // czy uruchomić procedurę usuwania pojazdów
TGround();
~TGround();
@@ -308,7 +307,9 @@ public:
void DynamicRemove(TDynamicObject *dyn);
void TerrainRead(std::string const &f);
void TerrainWrite();
#ifdef EU07_USE_OLD_GROUNDCODE
void Silence(vector3 gdzie);
#endif
};
//---------------------------------------------------------------------------

View File

@@ -103,7 +103,7 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
fStep = fNewStep;
if (fLength <= 0) {
ErrorLog( "Bad geometry: zero length spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
ErrorLog( "Bad track: zero length spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
fLength = 0.01; // crude workaround TODO: fix this properly
/*
return false; // zerowe nie mogą być
@@ -205,7 +205,7 @@ double TSegment::GetTFromS(double const s) const
// Newton's method failed. If this happens, increase iterations or
// tolerance or integration accuracy.
// return -1; //Ra: tu nigdy nie dojdzie
ErrorLog( "Bad geometry: shape estimation failed for spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
ErrorLog( "Bad track: shape estimation failed for spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
// MessageBox(0,"Too many iterations","GetTFromS",MB_OK);
return fTime;
};

131
Track.cpp
View File

@@ -185,6 +185,7 @@ TTrack::sort_by_material( TTrack const *Left, TTrack const *Right ) {
TTrack * TTrack::Create400m(int what, double dx)
{ // tworzenie toru do wstawiania taboru podczas konwersji na E3D
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode *tmp = new TGroundNode(TP_TRACK); // node
TTrack *trk = tmp->pTrack;
trk->m_visible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
@@ -195,11 +196,22 @@ TTrack * TTrack::Create400m(int what, double dx)
TSubRect *r = Global::pGround->GetSubRect(tmp->pCenter.x, tmp->pCenter.z);
r->NodeAdd(tmp); // dodanie toru do segmentu
r->Sort(); //żeby wyświetlał tabor z dodanego toru
#else
auto *trk = new TTrack( "auto_400m" );
trk->m_visible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
trk->iCategoryFlag = what; // taki sam typ plus informacja, że dodatkowy
trk->Init(); // utworzenie segmentu
trk->Segment->Init( vector3( -dx, 0, 0 ), vector3( -dx, 0, 400 ), 10.0, 0, 0 ); // prosty
trk->location( glm::dvec3{ -dx, 0, 200 } ); //środek, aby się mogło wyświetlić
simulation::Paths.insert( trk );
simulation::Region->insert_path( trk, scene::scratch_data() );
#endif
return trk;
};
TTrack * TTrack::NullCreate(int dir)
{ // tworzenie toru wykolejającego od strony (dir), albo pętli dla samochodów
#ifdef EU07_USE_OLD_GROUNDCODE
TGroundNode *tmp = new TGroundNode( TP_TRACK );
TGroundNode *tmp2 = nullptr; // node
TTrack *trk = tmp->pTrack; // tor; UWAGA! obrotnica może generować duże ilości tego
@@ -298,6 +310,100 @@ TTrack * TTrack::NullCreate(int dir)
r->NodeAdd( tmp2 ); // drugiego też
r->Sort(); //żeby wyświetlał tabor z dodanego toru
}
#else
TTrack
*trk { nullptr },
*trk2 { nullptr };
trk = new TTrack( "auto_null" );
trk->m_visible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
trk->iCategoryFlag = (iCategoryFlag & 15) | 0x80; // taki sam typ plus informacja, że dodatkowy
float r1, r2;
Segment->GetRolls(r1, r2); // pobranie przechyłek na początku toru
vector3 p1, cv1, cv2, p2; // będziem tworzyć trajektorię lotu
if (iCategoryFlag & 1)
{ // tylko dla kolei
trk->iDamageFlag = 128; // wykolejenie
trk->fVelocity = 0.0; // koniec jazdy
trk->Init(); // utworzenie segmentu
switch (dir)
{ //łączenie z nowym torem
case 0:
p1 = Segment->FastGetPoint_0();
p2 = p1 - 450.0 * Normalize(Segment->GetDirection1());
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk->Segment->Init(p1, p2, 5, -RadToDeg(r1), 70.0);
ConnectPrevPrev(trk, 0);
break;
case 1:
p1 = Segment->FastGetPoint_1();
p2 = p1 - 450.0 * Normalize(Segment->GetDirection2());
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk->Segment->Init(p1, p2, 5, RadToDeg(r2), 70.0);
ConnectNextPrev(trk, 0);
break;
case 3: // na razie nie możliwe
p1 = SwitchExtension->Segments[1]->FastGetPoint_1(); // koniec toru drugiego zwrotnicy
p2 = p1 - 450.0 * Normalize( SwitchExtension->Segments[1]->GetDirection2()); // przedłużenie na wprost
trk->Segment->Init(p1, p2, 5, RadToDeg(r2), 70.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
ConnectNextPrev(trk, 0);
// trk->ConnectPrevNext(trk,dir);
SetConnections(1); // skopiowanie połączeń
Switch(1); // bo się przełączy na 0, a to coś chce się przecież wykoleić na bok
break; // do drugiego zwrotnicy... nie zadziała?
}
}
else
{ // tworznie pętelki dla samochodów
trk->fVelocity = 20.0; // zawracanie powoli
trk->fRadius = 20.0; // promień, aby się dodawało do tabelki prędkości i liczyło narastająco
trk->Init(); // utworzenie segmentu
trk2 = new TTrack( "auto_null" );
trk2->iCategoryFlag =
(iCategoryFlag & 15) | 0x80; // taki sam typ plus informacja, że dodatkowy
trk2->m_visible = false;
trk2->fVelocity = 20.0; // zawracanie powoli
trk2->fRadius = 20.0; // promień, aby się dodawało do tabelki prędkości i liczyło narastająco
trk2->Init(); // utworzenie segmentu
trk->m_name = m_name + ":loopstart";
trk2->m_name = m_name + ":loopfinish";
switch (dir)
{ //łączenie z nowym torem
case 0:
p1 = Segment->FastGetPoint_0();
cv1 = -20.0 * Normalize(Segment->GetDirection1()); // pierwszy wektor kontrolny
p2 = p1 + cv1 + cv1; // 40m
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk->Segment->Init(p1, p1 + cv1, p2 + vector3(-cv1.z, cv1.y, cv1.x), p2, 2, -RadToDeg(r1), 0.0);
ConnectPrevPrev(trk, 0);
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk2->Segment->Init(p1, p1 + cv1, p2 + vector3(cv1.z, cv1.y, -cv1.x), p2, 2, -RadToDeg(r1), 0.0);
trk2->iPrevDirection = 0; // zwrotnie do tego samego odcinka
break;
case 1:
p1 = Segment->FastGetPoint_1();
cv1 = -20.0 * Normalize(Segment->GetDirection2()); // pierwszy wektor kontrolny
p2 = p1 + cv1 + cv1;
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk->Segment->Init(p1, p1 + cv1, p2 + vector3(-cv1.z, cv1.y, cv1.x), p2, 2, RadToDeg(r2), 0.0);
ConnectNextPrev(trk, 0);
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk2->Segment->Init(p1, p1 + cv1, p2 + vector3(cv1.z, cv1.y, -cv1.x), p2, 2, RadToDeg(r2), 0.0);
trk2->iPrevDirection = 1; // zwrotnie do tego samego odcinka
break;
}
trk2->trPrev = this;
trk->ConnectNextNext(trk2, 1); // połączenie dwóch dodatkowych odcinków punktami 2
}
// trzeba jeszcze dodać do odpowiedniego segmentu, aby się renderowały z niego pojazdy
trk->location( glm::dvec3{ 0.5 * ( p1 + p2 ) } ); //środek, aby się mogło wyświetlić
simulation::Paths.insert( trk );
simulation::Region->insert_path( trk, scene::scratch_data() );
if( trk2 ) {
trk2->location( trk->location() ); // ten sam środek jest
simulation::Paths.insert( trk2 );
simulation::Region->insert_path( trk2, scene::scratch_data() );
}
#endif
return trk;
};
@@ -473,7 +579,20 @@ void TTrack::Load(cParser *parser, vector3 pOrigin)
null_handle :
GfxRenderer.Fetch_Material( str ) );
parser->getTokens(3);
*parser >> fTexHeight1 >> fTexWidth >> fTexSlope;
*parser
>> fTexHeight1
>> fTexWidth
>> fTexSlope;
if( fTexLength != 4.f ) {
// force defaults for malformed track definitions
bool paramsvalid { true };
if( fTexHeight1 == 0.f ) { fTexHeight1 = 0.6f; paramsvalid = false; }
if( fTexWidth == 0.f ) { fTexWidth = 0.9f; paramsvalid = false; }
if( fTexSlope == 0.f ) { fTexSlope = 0.9f; paramsvalid = false; }
if( false == paramsvalid ) {
ErrorLog( "Bad track: one or more of texture dimensions set to 0 for track \"" + name() + "\" in file \"" + parser->Name() + "\" (line " + std::to_string( parser->Line() - 1 ) + ")" );
}
}
if (iCategoryFlag & 4)
fTexHeight1 = -fTexHeight1; // rzeki mają wysokość odwrotnie niż drogi
}
@@ -2167,6 +2286,9 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
void TTrack::EnvironmentSet()
{ // ustawienie zmienionego światła
#ifdef EU07_USE_OLD_GROUNDCODE
::glColor4f( 1.f, 1.f, 1.f, 1.f );
#endif
switch( eEnvironment ) {
case e_canyon: {
Global::DayLight.apply_intensity( 0.4f );
@@ -2801,7 +2923,14 @@ path_table::InitTracks() {
int connection { -1 };
TTrack *matchingtrack { nullptr };
#ifdef EU07_IGNORE_LEGACYPROCESSINGORDER
for( auto *track : m_items ) {
#else
// NOTE: legacy code peformed item operations last-to-first due to way the items were added to the list
// this had impact in situations like two possible connection candidates, where only the first one would be used
for( auto first = std::rbegin(m_items); first != std::rend(m_items); ++first ) {
auto *track = *first;
#endif
track->AssignEvents(
simulation::Events.FindEvent( track->asEvent0Name ),

View File

@@ -374,55 +374,59 @@ TTraction::create_geometry( geometrybank_handle const &Bank ) {
int TTraction::TestPoint(glm::dvec3 const &Point)
{ // sprawdzanie, czy przęsła można połączyć
if (!hvNext[0])
if( glm::all( glm::epsilonEqual( Point, pPoint1, 0.025 ) ) )
return 0;
if (!hvNext[1])
if( glm::all( glm::epsilonEqual( Point, pPoint2, 0.025 ) ) )
return 1;
if( ( hvNext[ 0 ] == nullptr )
&& ( glm::all( glm::epsilonEqual( Point, pPoint1, 0.025 ) ) ) ) {
return 0;
}
if( ( hvNext[ 1 ] == nullptr )
&& ( glm::all( glm::epsilonEqual( Point, pPoint2, 0.025 ) ) ) ) {
return 1;
}
return -1;
};
void TTraction::Connect(int my, TTraction *with, int to)
{ //łączenie segmentu (with) od strony (my) do jego (to)
if (my)
{ // do mojego Point2
hvNext[1] = with;
iNext[1] = to;
}
else
{ // do mojego Point1
hvNext[0] = with;
iNext[0] = to;
}
if (to)
{ // do jego Point2
with->hvNext[1] = this;
with->iNext[1] = my;
}
else
{ // do jego Point1
with->hvNext[0] = this;
with->iNext[0] = my;
}
if (hvNext[0]) // jeśli z obu stron podłączony
if (hvNext[1])
iLast = 0; // to nie jest ostatnim
if (with->hvNext[0]) // temu też, bo drugi raz łączenie się nie nie wykona
if (with->hvNext[1])
with->iLast = 0; // to nie jest ostatnim
};
//łączenie segmentu (with) od strony (my) do jego (to)
void
TTraction::Connect(int my, TTraction *with, int to) {
bool TTraction::WhereIs()
{ // ustalenie przedostatnich przęseł
if (iLast)
return (iLast == 1); // ma już ustaloną informację o położeniu
if (hvNext[0] ? hvNext[0]->iLast == 1 : false) // jeśli poprzedni jest ostatnim
iLast = 2; // jest przedostatnim
else if (hvNext[1] ? hvNext[1]->iLast == 1 : false) // jeśli następny jest ostatnim
iLast = 2; // jest przedostatnim
return (iLast == 1); // ostatnie będą dostawać zasilanie
};
hvNext[ my ] = with;
iNext[ my ] = to;
if( ( hvNext[ 0 ] != nullptr )
&& ( hvNext[ 1 ] != nullptr ) ) {
// jeśli z obu stron podłączony to nie jest ostatnim
iLast = 0;
}
with->hvNext[ to ] = this;
with->iNext[ to ] = my;
if( ( with->hvNext[ 0 ] != nullptr )
&& ( with->hvNext[ 1 ] != nullptr ) ) {
// temu też, bo drugi raz łączenie się nie nie wykona
with->iLast = 0;
}
}
// ustalenie przedostatnich przęseł
bool TTraction::WhereIs() {
if( iLast ) {
// ma już ustaloną informację o położeniu
return ( iLast & 1 );
}
for( int endindex = 0; endindex < 2; ++endindex ) {
if( hvNext[ endindex ] == nullptr ) {
// no neighbour piece means this one is last
iLast |= 1;
}
else if( hvNext[ endindex ]->hvNext[ 1 - iNext[ endindex ] ] == nullptr ) {
// otherwise if that neighbour has no further connection on the opposite end then this piece is second-last
iLast |= 2;
}
}
return (iLast & 1); // ostatnie będą dostawać zasilanie
}
void TTraction::Init()
{ // przeliczenie parametrów
@@ -585,30 +589,41 @@ TTraction::wire_color() const {
case 1: {
// czerwone z podłączonym zasilaniem 1
color.r = 1.0f;
color.g = 0.0f;
color.b = 0.0f;
// color.r = 1.0f;
// color.g = 0.0f;
// color.b = 0.0f;
// cyan
color = glm::vec3 { 0.f, 174.f / 255.f, 239.f / 255.f };
break;
}
case 2: {
// zielone z podłączonym zasilaniem 2
color.r = 0.0f;
color.g = 1.0f;
color.b = 0.0f;
// color.r = 0.0f;
// color.g = 1.0f;
// color.b = 0.0f;
// yellow
color = glm::vec3 { 240.f / 255.f, 228.f / 255.f, 0.f };
break;
}
case 3: {
//żółte z podłączonym zasilaniem z obu stron
color.r = 1.0f;
color.g = 1.0f;
color.b = 0.0f;
// color.r = 1.0f;
// color.g = 1.0f;
// color.b = 0.0f;
// green
color = glm::vec3 { 0.f, 239.f / 255.f, 118.f / 255.f };
break;
}
case 4: {
// niebieskie z podłączonym zasilaniem
color.r = 0.5f;
color.g = 0.5f;
color.b = 1.0f;
// color.r = 0.5f;
// color.g = 0.5f;
// color.b = 1.0f;
// white for powered, red for ends
color = (
psPowered != nullptr ?
glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f } :
glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f } );
break;
}
default: { break; }
@@ -618,6 +633,46 @@ TTraction::wire_color() const {
color.g *= 0.6f;
color.b *= 0.6f;
}
/*
switch( iTries ) {
case 0: {
color = glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f }; // red
break;
}
case 1: {
color = glm::vec3{ 240.f / 255.f, 228.f / 255.f, 0.f }; // yellow
break;
}
case 5: {
color = glm::vec3{ 0.f / 255.f, 239.f / 255.f, 118.f / 255.f }; // green
break;
}
default: {
color = glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f };
break;
}
}
*/
/*
switch( iLast ) {
case 0: {
color = glm::vec3{ 240.f / 255.f, 228.f / 255.f, 0.f }; // yellow
break;
}
case 1: {
color = glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f }; // red
break;
}
case 2: {
color = glm::vec3{ 0.f / 255.f, 239.f / 255.f, 118.f / 255.f }; // green
break;
}
default: {
color = glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f };
break;
}
}
*/
}
return color;
}
@@ -660,18 +715,21 @@ traction_table::InitTraction() {
}
}
#ifdef EU07_IGNORE_LEGACYPROCESSINGORDER
for( auto *traction : m_items ) {
if (!traction->hvNext[0]) {
#else
// NOTE: legacy code peformed item operations last-to-first due to way the items were added to the list
// this had impact in situations like two possible connection candidates, where only the first one would be used
for( auto first = std::rbegin(m_items); first != std::rend(m_items); ++first ) {
auto *traction = *first;
#endif
if( traction->hvNext[ 0 ] == nullptr ) {
// tylko jeśli jeszcze nie podłączony
std::tie( matchingtraction, connection ) = simulation::Region->find_traction( traction->pPoint1, traction );
switch (connection) {
case 0: {
traction->Connect( 0, matchingtraction, 0 );
break;
}
case 0:
case 1: {
traction->Connect( 0, matchingtraction, 1 );
traction->Connect( 0, matchingtraction, connection );
break;
}
default: {
@@ -691,8 +749,8 @@ traction_table::InitTraction() {
//(tmp->psSection) jest podstacją, a (Traction->psSection) nazwą sekcji
matchingtraction->PowerSet( traction->psSection ); // zastąpienie wskazaniem sekcji
}
else if( ( false == traction->psSection->bSection ) &&
( true == matchingtraction->psSection->bSection ) ) {
else if( ( false == traction->psSection->bSection )
&& ( true == matchingtraction->psSection->bSection ) ) {
//(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
traction->PowerSet( matchingtraction->psSection ); // zastąpienie wskazaniem sekcji
}
@@ -704,16 +762,13 @@ traction_table::InitTraction() {
}
}
}
if (!traction->hvNext[1]) {
if( traction->hvNext[ 1 ] == nullptr ) {
// tylko jeśli jeszcze nie podłączony
std::tie( matchingtraction, connection ) = simulation::Region->find_traction( traction->pPoint2, traction );
switch (connection) {
case 0: {
traction->Connect( 1, matchingtraction, 0 );
break;
}
case 0:
case 1: {
traction->Connect( 1, matchingtraction, 1 );
traction->Connect( 1, matchingtraction, connection );
break;
}
default: {
@@ -770,7 +825,7 @@ traction_table::InitTraction() {
if( ( traction->asParallel == "none" )
|| ( traction->asParallel == "*" ) ) {
// jeśli nieokreślone
traction->iLast = 2; // jakby przedostatni - niech po prostu szuka (iLast już przeliczone)
traction->iLast |= 2; // jakby przedostatni - niech po prostu szuka (iLast już przeliczone)
}
else if( traction->hvParallel == nullptr ) {
// jeśli jeszcze nie został włączony w kółko
@@ -792,7 +847,7 @@ traction_table::InitTraction() {
}
}
}
if( traction->iTries > 0 ) {
if( traction->iTries == 5 ) {
// jeśli zaznaczony do podłączenia
// wypełnianie tabeli końców w celu szukania im połączeń
ends.emplace_back( traction );

View File

@@ -27,7 +27,7 @@ class TTraction : public editor::basic_node {
TTractionPowerSource *psPowered { nullptr }; // ustawione tylko dla bezpośrednio zasilanego przęsła
TTraction *hvNext[ 2 ] { nullptr, nullptr }; //łączenie drutów w sieć
int iNext[ 2 ] { 0, 0 }; // do którego końca się łączy
int iLast { 1 }; //że niby ostatni drut // ustawiony bit 0, jeśli jest ostatnim drutem w sekcji; bit1 - przedostatni
int iLast { 0 }; //że niby ostatni drut // ustawiony bit 0, jeśli jest ostatnim drutem w sekcji; bit1 - przedostatni
public:
glm::dvec3 pPoint1, pPoint2, pPoint3, pPoint4;
glm::dvec3 vParametric; // współczynniki równania parametrycznego odcinka
@@ -46,7 +46,7 @@ class TTraction : public editor::basic_node {
std::string asParallel; // nazwa przęsła, z którym może być bieżnia wspólna
TTraction *hvParallel { nullptr }; // jednokierunkowa i zapętlona lista przęseł ewentualnej bieżni wspólnej
float fResistance[ 2 ] { -1.0f, -1.0f }; // rezystancja zastępcza do punktu zasilania (0: przęsło zasilane, <0: do policzenia)
int iTries { 0 };
int iTries { 1 }; // 0 is used later down the road to mark directly powered pieces
int PowerState { 0 }; // type of incoming power, if any
// visualization data
glm::dvec3 m_origin;

View File

@@ -465,7 +465,11 @@ void TWorld::OnKeyDown(int cKey)
}
else // również przeskakiwanie
{ // Ra: to z tą kamerą (Camera.Pos i Global::pCameraPosition) jest trochę bez sensu
#ifdef EU07_USE_OLD_GROUNDCODE
// NOTE: does it even work? it seems to render the sounds before the camera is actually moved
// so the listener is still in range...
Ground.Silence( Global::pCameraPosition ); // wyciszenie wszystkiego z poprzedniej pozycji
#endif
Global::SetCameraPosition( Global::FreeCameraInit[i] ); // nowa pozycja dla generowania obiektów
Camera.Init(Global::FreeCameraInit[i],
Global::FreeCameraInitAngle[i]); // przestawienie
@@ -918,8 +922,9 @@ void TWorld::FollowView(bool wycisz) {
if (Controlled) // jest pojazd do prowadzenia?
{
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.Silence( Camera.Pos ); // wyciszenie dźwięków z poprzedniej pozycji
#endif
if (FreeFlyModeFlag)
{ // jeżeli poza kabiną, przestawiamy w jej okolicę - OK
if( Train ) {
@@ -937,7 +942,9 @@ void TWorld::FollowView(bool wycisz) {
if( wycisz ) {
// wyciszenie dźwięków z poprzedniej pozycji
// trzymanie prawego w kabinie daje marny efekt
#ifdef EU07_USE_OLD_GROUNDCODE
Ground.Silence( Camera.Pos );
#endif
}
Camera.Pos = Train->pMechPosition;
Camera.Roll = std::atan(Train->pMechShake.x * Train->fMechRoll); // hustanie kamery na boki

View File

@@ -122,7 +122,9 @@ private:
TCamera Camera;
TCamera DebugCamera;
#ifdef EU07_USE_OLD_GROUNDCODE
TGround Ground;
#endif
world_environment Environment;
TTrain *Train;
TDynamicObject *pDynamicNearest;

View File

@@ -1921,8 +1921,9 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
// render
#ifdef EU07_USE_DEBUG_CULLING
// debug
::glLineWidth( 2.f );
float const width = section->m_area.radius;
float const height = scene::EU07_SECTIONSIZE * 0.2f;
float const height = section->m_area.radius * 0.2f;
glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D );
glColor3ub( 255, 128, 128 );
@@ -1947,6 +1948,7 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
glColor3ub( 255, 255, 255 );
glEnable( GL_TEXTURE_2D );
glEnable( GL_LIGHTING );
glLineWidth( 1.f );
#endif
// shapes
for( auto const &shape : section->m_shapes ) { Render( shape, true ); }
@@ -2024,7 +2026,7 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
#ifdef EU07_USE_DEBUG_CULLING
// debug
float const width = cell->m_area.radius;
float const height = scene::EU07_CELLSIZE * 0.15f;
float const height = cell->m_area.radius * 0.15f;
glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D );
glColor3ub( 255, 255, 0 );
@@ -3253,7 +3255,7 @@ opengl_renderer::Render_Alpha( TTraction *Traction ) {
}
// rysuj jesli sa druty i nie zerwana
if( ( Traction->Wires == 0 )
|| ( true == TestFlag( Traction->DamageFlag, 128 ) ) ) {
|| ( true == TestFlag( Traction->DamageFlag, 128 ) ) ) {
return;
}
// setup

View File

@@ -65,7 +65,7 @@ basic_cell::update_traction( TDynamicObject *Vehicle, int const Pantographindex
auto pantograph = Vehicle->pants[ Pantographindex ].fParamPants;
auto const pantographposition = position + ( vLeft * pantograph->vPos.z ) + ( vUp * pantograph->vPos.y ) + ( vFront * pantograph->vPos.x );
for( auto *traction : m_traction ) {
for( auto *traction : m_directories.traction ) {
// współczynniki równania parametrycznego
auto const paramfrontdot = glm::dot( traction->vParametric, vFront );
@@ -174,6 +174,11 @@ basic_cell::insert( shape_node Shape ) {
m_active = true;
// re-calculate cell radius, in case shape geometry extends outside the cell's boundaries
m_area.radius = std::max<float>(
m_area.radius,
glm::length( m_area.center - Shape.data().area.center ) + Shape.data().area.radius );
auto const &shapedata { Shape.data() };
auto &shapes = (
shapedata.translucent ?
@@ -507,7 +512,7 @@ basic_section::update_traction( TDynamicObject *Vehicle, int const Pantographind
auto pantograph = Vehicle->pants[ Pantographindex ].fParamPants;
auto const pantographposition = position + ( vLeft * pantograph->vPos.z ) + ( vUp * pantograph->vPos.y ) + ( vFront * pantograph->vPos.x );
auto const radius { 0.0 }; // { EU07_CELLSIZE * 0.5 }; // experimentally limited, check if it has any negative effect
auto const radius { EU07_CELLSIZE * 0.5 };
for( auto &cell : m_cells ) {
// we reject early cells which aren't within our area of interest
@@ -728,7 +733,7 @@ basic_region::update_traction( TDynamicObject *Vehicle, int const Pantographinde
auto const pant0 = position + ( vLeft * p->vPos.z ) + ( vUp * p->vPos.y ) + ( vFront * p->vPos.x );
p->PantTraction = std::numeric_limits<double>::max(); // taka za duża wartość
auto const &sectionlist = sections( pant0, 0.0 );
auto const &sectionlist = sections( pant0, EU07_CELLSIZE * 0.5 );
for( auto *section : sectionlist ) {
section->update_traction( Vehicle, Pantographindex );
}

View File

@@ -308,16 +308,14 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
auto *path { deserialize_path( Input, Scratchpad, nodedata ) };
// duplicates of named tracks are currently experimentally allowed
if( simulation::Paths.insert( path ) ) {
simulation::Region->insert_path( path, Scratchpad );
}
else {
if( false == simulation::Paths.insert( path ) ) {
ErrorLog( "Bad scenario: track with duplicate name \"" + path->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
/*
delete path;
delete pathnode;
*/
}
simulation::Region->insert_path( path, Scratchpad );
}
else if( nodedata.type == "traction" ) {
@@ -325,12 +323,10 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
// traction loading is optional
if( traction == nullptr ) { return; }
if( simulation::Traction.insert( traction ) ) {
simulation::Region->insert_traction( traction, Scratchpad );
}
else {
if( false == simulation::Traction.insert( traction ) ) {
ErrorLog( "Bad scenario: traction piece with duplicate name \"" + traction->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}
simulation::Region->insert_traction( traction, Scratchpad );
}
else if( nodedata.type == "tractionpowersource" ) {
@@ -338,15 +334,13 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
// traction loading is optional
if( powersource == nullptr ) { return; }
if( simulation::Powergrid.insert( powersource ) ) {
/*
// TODO: implement this
simulation::Region.insert_powersource( powersource, Scratchpad );
*/
}
else {
if( false == simulation::Powergrid.insert( powersource ) ) {
ErrorLog( "Bad scenario: power grid source with duplicate name \"" + powersource->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}
/*
// TODO: implement this
simulation::Region.insert_powersource( powersource, Scratchpad );
*/
}
else if( nodedata.type == "model" ) {
@@ -382,12 +376,10 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
// model import can potentially fail
if( instance == nullptr ) { return; }
if( simulation::Instances.insert( instance ) ) {
simulation::Region->insert_instance( instance, Scratchpad );
}
else {
if( false == simulation::Instances.insert( instance ) ) {
ErrorLog( "Bad scenario: 3d model instance with duplicate name \"" + instance->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}
simulation::Region->insert_instance( instance, Scratchpad );
}
}
else if( ( nodedata.type == "triangles" )
@@ -412,42 +404,36 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
else if( nodedata.type == "memcell" ) {
auto *memorycell { deserialize_memorycell( Input, Scratchpad, nodedata ) };
if( simulation::Memory.insert( memorycell ) ) {
/*
// TODO: implement this
simulation::Region.insert_memorycell( memorycell, Scratchpad );
*/
}
else {
if( false == simulation::Memory.insert( memorycell ) ) {
ErrorLog( "Bad scenario: memory cell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}
/*
// TODO: implement this
simulation::Region.insert_memorycell( memorycell, Scratchpad );
*/
}
else if( nodedata.type == "eventlauncher" ) {
auto *eventlauncher{ deserialize_eventlauncher( Input, Scratchpad, nodedata ) };
if( simulation::Events.insert( eventlauncher ) ) {
auto *eventlauncher { deserialize_eventlauncher( Input, Scratchpad, nodedata ) };
if( false == simulation::Events.insert( eventlauncher ) ) {
ErrorLog( "Bad scenario: event launcher with duplicate name \"" + eventlauncher->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}
// event launchers can be either global, or local with limited range of activation
// each gets assigned different caretaker
if( true == eventlauncher->IsGlobal() ) {
simulation::Events.queue( eventlauncher );
}
else {
simulation::Region->insert_launcher( eventlauncher, Scratchpad );
}
if( true == eventlauncher->IsGlobal() ) {
simulation::Events.queue( eventlauncher );
}
else {
ErrorLog( "Bad scenario: event launcher with duplicate name \"" + eventlauncher->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
simulation::Region->insert_launcher( eventlauncher, Scratchpad );
}
}
else if( nodedata.type == "sound" ) {
auto *sound { deserialize_sound( Input, Scratchpad, nodedata ) };
if( simulation::Sounds.insert( sound ) ) {
simulation::Region->insert_sound( sound, Scratchpad );
}
else {
if( false == simulation::Sounds.insert( sound ) ) {
ErrorLog( "Bad scenario: sound node with duplicate name \"" + sound->m_name + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}
simulation::Region->insert_sound( sound, Scratchpad );
}
}
@@ -476,7 +462,7 @@ state_manager::deserialize_endorigin( cParser &Input, scene::scratch_data &Scrat
Scratchpad.location_offset.pop();
}
else {
ErrorLog( "Bad origin: endorigin instruction with empty origin stack in file \"" + Input.Name() + "\" (line " + to_string( Input.Line() - 1 ) + ")" );
ErrorLog( "Bad origin: endorigin instruction with empty origin stack in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
}
}
@@ -530,7 +516,7 @@ state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratc
if( true == Scratchpad.trainset.is_open ) {
// shouldn't happen but if it does wrap up currently open trainset and report an error
deserialize_endtrainset( Input, Scratchpad );
ErrorLog( "Bad scenario: encountered nested trainset definitions in file \"" + Input.Name() + "\" (line " + to_string( Input.Line() ) + ")" );
ErrorLog( "Bad scenario: encountered nested trainset definitions in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() ) + ")" );
}
Scratchpad.trainset = scene::scratch_data::trainset_data();
@@ -550,7 +536,7 @@ state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scr
if( ( false == Scratchpad.trainset.is_open )
|| ( true == Scratchpad.trainset.vehicles.empty() ) ) {
// not bloody likely but we better check for it just the same
ErrorLog( "Bad trainset: empty trainset defined in file \"" + Input.Name() + "\" (line " + to_string( Input.Line() - 1 ) + ")" );
ErrorLog( "Bad trainset: empty trainset defined in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
Scratchpad.trainset.is_open = false;
return;
}

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 17
#define VERSION_MINOR 916
#define VERSION_MINOR 1020
#define VERSION_REVISION 0