mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 13:19:19 +02:00
continued refacoring: vehicles, events, memcells, tracks, traction, traction power sources; minor readability enhancements and bug fixes
This commit is contained in:
17
AdvSound.cpp
17
AdvSound.cpp
@@ -19,12 +19,7 @@ TAdvancedSound::~TAdvancedSound()
|
||||
// SoundShut.Stop();
|
||||
}
|
||||
|
||||
void TAdvancedSound::Free()
|
||||
{
|
||||
}
|
||||
|
||||
void TAdvancedSound::Init( std::string const &NameOn, std::string const &Name, std::string const &NameOff, double DistanceAttenuation,
|
||||
vector3 const &pPosition)
|
||||
void TAdvancedSound::Init( std::string const &NameOn, std::string const &Name, std::string const &NameOff, double DistanceAttenuation, Math3D::vector3 const &pPosition)
|
||||
{
|
||||
SoundStart.Init(NameOn, DistanceAttenuation, pPosition.x, pPosition.y, pPosition.z, true);
|
||||
SoundCommencing.Init(Name, DistanceAttenuation, pPosition.x, pPosition.y, pPosition.z, true);
|
||||
@@ -47,7 +42,7 @@ void TAdvancedSound::Init( std::string const &NameOn, std::string const &Name, s
|
||||
SoundShut.FA = 0.0;
|
||||
}
|
||||
|
||||
void TAdvancedSound::Load(cParser &Parser, vector3 const &pPosition)
|
||||
void TAdvancedSound::Load(cParser &Parser, Math3D::vector3 const &pPosition)
|
||||
{
|
||||
std::string nameon, name, nameoff;
|
||||
double attenuation;
|
||||
@@ -62,7 +57,7 @@ void TAdvancedSound::Load(cParser &Parser, vector3 const &pPosition)
|
||||
Init( nameon, name, nameoff, attenuation, pPosition );
|
||||
}
|
||||
|
||||
void TAdvancedSound::TurnOn(bool ListenerInside, vector3 NewPosition)
|
||||
void TAdvancedSound::TurnOn(bool ListenerInside, Math3D::vector3 NewPosition)
|
||||
{
|
||||
// hunter-311211: nie trzeba czekac na ponowne odtworzenie dzwieku, az sie wylaczy
|
||||
if ((State == ss_Off || State == ss_ShuttingDown) && (SoundStart.AM > 0))
|
||||
@@ -76,7 +71,7 @@ void TAdvancedSound::TurnOn(bool ListenerInside, vector3 NewPosition)
|
||||
}
|
||||
}
|
||||
|
||||
void TAdvancedSound::TurnOff(bool ListenerInside, vector3 NewPosition)
|
||||
void TAdvancedSound::TurnOff(bool ListenerInside, Math3D::vector3 NewPosition)
|
||||
{
|
||||
if ((State == ss_Commencing || State == ss_Starting) && (SoundShut.AM > 0))
|
||||
{
|
||||
@@ -90,7 +85,7 @@ void TAdvancedSound::TurnOff(bool ListenerInside, vector3 NewPosition)
|
||||
}
|
||||
}
|
||||
|
||||
void TAdvancedSound::Update(bool ListenerInside, vector3 NewPosition)
|
||||
void TAdvancedSound::Update(bool ListenerInside, Math3D::vector3 NewPosition)
|
||||
{
|
||||
if ((State == ss_Commencing) && (SoundCommencing.AM > 0))
|
||||
{
|
||||
@@ -126,7 +121,7 @@ void TAdvancedSound::Update(bool ListenerInside, vector3 NewPosition)
|
||||
}
|
||||
}
|
||||
|
||||
void TAdvancedSound::UpdateAF(double A, double F, bool ListenerInside, vector3 NewPosition)
|
||||
void TAdvancedSound::UpdateAF(double A, double F, bool ListenerInside, Math3D::vector3 NewPosition)
|
||||
{ // update, ale z amplituda i czestotliwoscia
|
||||
if( State == ss_Off ) {
|
||||
return;
|
||||
|
||||
19
AdvSound.h
19
AdvSound.h
@@ -13,13 +13,13 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "RealSound.h"
|
||||
#include "parser.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
enum TSoundState {
|
||||
|
||||
ss_Off,
|
||||
ss_Starting,
|
||||
ss_Commencing,
|
||||
ss_ShuttingDown
|
||||
} TSoundState;
|
||||
};
|
||||
|
||||
class TAdvancedSound
|
||||
{ // klasa dźwięków mających początek, dowolnie długi środek oraz zakończenie (np. Rp1)
|
||||
@@ -36,13 +36,12 @@ class TAdvancedSound
|
||||
public:
|
||||
TAdvancedSound() = default;
|
||||
~TAdvancedSound();
|
||||
void Init( std::string const &NameOn, std::string const &Name, std::string const &NameOff, double DistanceAttenuation, vector3 const &pPosition);
|
||||
void Load(cParser &Parser, vector3 const &pPosition);
|
||||
void TurnOn(bool ListenerInside, vector3 NewPosition);
|
||||
void TurnOff(bool ListenerInside, vector3 NewPosition);
|
||||
void Free();
|
||||
void Update(bool ListenerInside, vector3 NewPosition);
|
||||
void UpdateAF(double A, double F, bool ListenerInside, vector3 NewPosition);
|
||||
void Init( std::string const &NameOn, std::string const &Name, std::string const &NameOff, double DistanceAttenuation, Math3D::vector3 const &pPosition);
|
||||
void Load(cParser &Parser, Math3D::vector3 const &pPosition);
|
||||
void TurnOn(bool ListenerInside, Math3D::vector3 NewPosition);
|
||||
void TurnOff(bool ListenerInside, Math3D::vector3 NewPosition);
|
||||
void Update(bool ListenerInside, Math3D::vector3 NewPosition);
|
||||
void UpdateAF(double A, double F, bool ListenerInside, Math3D::vector3 NewPosition);
|
||||
void CopyIfEmpty(TAdvancedSound &s);
|
||||
};
|
||||
|
||||
|
||||
@@ -759,22 +759,28 @@ void TAnimModel::LightSet(int n, float v)
|
||||
{ // ustawienie światła (n) na wartość (v)
|
||||
if (n >= iMaxNumLights)
|
||||
return; // przekroczony zakres
|
||||
lsLights[n] = TLightState(int(v));
|
||||
switch (lsLights[n])
|
||||
{ // interpretacja ułamka zależnie od typu
|
||||
case 0: // ustalenie czasu migotania, t<1s (f>1Hz), np. 0.1 => t=0.1 (f=10Hz)
|
||||
lsLights[ n ] = TLightState( static_cast<int>( v ) );
|
||||
switch( lsLights[ n ] ) {
|
||||
// interpretacja ułamka zależnie od typu
|
||||
case ls_Off: {
|
||||
// ustalenie czasu migotania, t<1s (f>1Hz), np. 0.1 => t=0.1 (f=10Hz)
|
||||
break;
|
||||
case 1: // ustalenie wypełnienia ułamkiem, np. 1.25 => zapalony przez 1/4 okresu
|
||||
}
|
||||
case ls_On: {
|
||||
// ustalenie wypełnienia ułamkiem, np. 1.25 => zapalony przez 1/4 okresu
|
||||
break;
|
||||
case 2: // ustalenie częstotliwości migotania, f<1Hz (t>1s), np. 2.2 => f=0.2Hz (t=5s)
|
||||
}
|
||||
case ls_Blink: {
|
||||
// ustalenie częstotliwości migotania, f<1Hz (t>1s), np. 2.2 => f=0.2Hz (t=5s)
|
||||
break;
|
||||
case 3: // 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
|
||||
}
|
||||
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
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
void TAnimModel::AnimUpdate(double dt)
|
||||
|
||||
@@ -176,7 +176,9 @@ private:
|
||||
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
||||
};
|
||||
|
||||
class instance_manager : public basic_table<TAnimModel> {
|
||||
|
||||
|
||||
class instance_table : public basic_table<TAnimModel> {
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class TMtableTime; // czas dla danego posterunku
|
||||
|
||||
class TController; // obiekt sterujący pociągiem (AI)
|
||||
|
||||
typedef enum
|
||||
enum TCommandType
|
||||
{ // binarne odpowiedniki komend w komórce pamięci
|
||||
cm_Unknown, // ciąg nierozpoznany (nie jest komendą)
|
||||
cm_Ready, // W4 zezwala na odjazd, ale semafor może zatrzymać
|
||||
@@ -51,6 +51,6 @@ typedef enum
|
||||
cm_OutsideStation,
|
||||
cm_Shunt,
|
||||
cm_Command // komenda pobierana z komórki
|
||||
} TCommandType;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
68
DynObj.cpp
68
DynObj.cpp
@@ -4150,7 +4150,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
||||
// Ra 15-01: gałka nastawy hamulca
|
||||
parser.getTokens();
|
||||
parser >> asAnimName;
|
||||
smBrakeMode = mdModel->GetFromName(asAnimName.c_str());
|
||||
smBrakeMode = mdModel->GetFromName(asAnimName);
|
||||
// jeszcze wczytać kąty obrotu dla poszczególnych ustawień
|
||||
}
|
||||
|
||||
@@ -4158,7 +4158,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
||||
// Ra 15-01: gałka nastawy hamulca
|
||||
parser.getTokens();
|
||||
parser >> asAnimName;
|
||||
smLoadMode = mdModel->GetFromName(asAnimName.c_str());
|
||||
smLoadMode = mdModel->GetFromName(asAnimName);
|
||||
// jeszcze wczytać kąty obrotu dla poszczególnych ustawień
|
||||
}
|
||||
|
||||
@@ -4170,7 +4170,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
||||
for (i = 0; i < iAnimType[ANIM_WHEELS]; ++i) // liczba osi
|
||||
{ // McZapkie-050402: wyszukiwanie kol o nazwie str*
|
||||
asAnimName = token + std::to_string(i + 1);
|
||||
pAnimations[i].smAnimated = mdModel->GetFromName(asAnimName.c_str()); // ustalenie submodelu
|
||||
pAnimations[i].smAnimated = mdModel->GetFromName(asAnimName); // ustalenie submodelu
|
||||
if (pAnimations[i].smAnimated)
|
||||
{ //++iAnimatedAxles;
|
||||
pAnimations[i].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu
|
||||
@@ -4311,8 +4311,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
||||
}
|
||||
}
|
||||
else
|
||||
ErrorLog("Bad model: " + asFileName + " - missed submodel " +
|
||||
asAnimName); // brak ramienia
|
||||
ErrorLog("Bad model: " + asFileName + " - missed submodel " + asAnimName); // brak ramienia
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4346,8 +4345,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
||||
}
|
||||
}
|
||||
else
|
||||
ErrorLog( "Bad model: " + asFileName + " - missed submodel " +
|
||||
asAnimName ); // brak ramienia
|
||||
ErrorLog( "Bad model: " + asFileName + " - missed submodel " + asAnimName ); // brak ramienia
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5393,3 +5391,59 @@ TDynamicObject::ConnectedEnginePowerSource( TDynamicObject const *Caller ) const
|
||||
// ...if we're still here, report lack of power source
|
||||
return MoverParameters->EnginePowerSource.SourceType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
vehicle_table::update( double Deltatime, int Iterationcount ) {
|
||||
// Ra: w zasadzie to trzeba by utworzyć oddzielną listę taboru do liczenia fizyki
|
||||
// na którą by się zapisywały wszystkie pojazdy będące w ruchu
|
||||
// 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 ) {
|
||||
// Ra: zmienić warunek na sprawdzanie pantografów w jednej zmiennej: czy pantografy i czy podniesione
|
||||
if( vehicle->MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) {
|
||||
/*
|
||||
// TODO: re-implement
|
||||
GetTraction( vehicle );
|
||||
*/
|
||||
}
|
||||
vehicle->MoverParameters->ComputeConstans();
|
||||
vehicle->CoupleDist();
|
||||
}
|
||||
if( Iterationcount > 1 ) {
|
||||
// ABu: ponizsze wykonujemy tylko jesli wiecej niz jedna iteracja
|
||||
for( int iteration = 0; iteration < ( Iterationcount - 1 ); ++iteration ) {
|
||||
for( auto *vehicle : m_items ) {
|
||||
vehicle->UpdateForce( Deltatime, Deltatime, false );
|
||||
}
|
||||
for( auto *vehicle : m_items ) {
|
||||
vehicle->FastUpdate( Deltatime );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto const totaltime { Deltatime * Iterationcount }; // całkowity czas
|
||||
|
||||
for( auto *vehicle : m_items ) {
|
||||
vehicle->UpdateForce( Deltatime, totaltime, true );
|
||||
}
|
||||
for( auto *vehicle : m_items ) {
|
||||
// Ra 2015-01: tylko tu przelicza sieć trakcyjną
|
||||
vehicle->Update( Deltatime, totaltime );
|
||||
}
|
||||
/*
|
||||
// TODO: re-implement
|
||||
if (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)
|
||||
{
|
||||
DynamicRemove(Current->DynamicObject); // usunięcie tego i podłączonych
|
||||
Current = nRootDynamic; // sprawdzanie listy od początku
|
||||
}
|
||||
bDynamicRemove = false; // na razie koniec
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
183
DynObj.h
183
DynObj.h
@@ -160,19 +160,17 @@ private: // położenie pojazdu w świecie oraz parametry ruchu
|
||||
TTrackParam tp; // parametry toru przekazywane do fizyki
|
||||
TTrackFollower Axle0; // oś z przodu (od sprzęgu 0)
|
||||
TTrackFollower Axle1; // oś z tyłu (od sprzęgu 1)
|
||||
int iAxleFirst; // numer pierwszej osi w kierunku ruchu (oś wiążąca pojazd z torem i wyzwalająca
|
||||
// eventy)
|
||||
int iAxleFirst; // numer pierwszej osi w kierunku ruchu (oś wiążąca pojazd z torem i wyzwalająca eventy)
|
||||
float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia
|
||||
Math3D::vector3 modelRot; // obrot pudła względem świata - do przeanalizowania, czy potrzebne!!!
|
||||
// bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów
|
||||
TDynamicObject * ABuFindNearestObject( TTrack *Track, TDynamicObject *MyPointer, int &CouplNr );
|
||||
|
||||
public: // parametry położenia pojazdu dostępne publicznie
|
||||
public:
|
||||
// parametry położenia pojazdu dostępne publicznie
|
||||
std::string asTrack; // nazwa toru początkowego; wywalić?
|
||||
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
|
||||
Math3D::matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
|
||||
TMoverParameters *MoverParameters; // parametry fizyki ruchu oraz przeliczanie
|
||||
// TMoverParameters *pControlled; //wskaźnik do sterowanego członu silnikowego
|
||||
TDynamicObject *NextConnected; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
|
||||
TDynamicObject *PrevConnected; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
|
||||
int NextConnectedNo; // numer sprzęgu podłączonego z tyłu
|
||||
@@ -182,7 +180,7 @@ public: // parametry położenia pojazdu dostępne publicznie
|
||||
|
||||
TPowerSource ConnectedEnginePowerSource( TDynamicObject const *Caller ) const;
|
||||
|
||||
public: // modele składowe pojazdu
|
||||
// modele składowe pojazdu
|
||||
TModel3d *mdModel; // model pudła
|
||||
TModel3d *mdLoad; // model zmiennego ładunku
|
||||
TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h
|
||||
@@ -201,7 +199,8 @@ public: // modele składowe pojazdu
|
||||
bool SectionLightsActive { false }; // flag indicating whether section lights were set.
|
||||
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
|
||||
|
||||
private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
|
||||
private:
|
||||
// zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
|
||||
material_data m_materialdata;
|
||||
|
||||
public:
|
||||
@@ -217,12 +216,9 @@ public: // modele składowe pojazdu
|
||||
TAnim *pAnimations; // obiekty animujące (zawierają wskaźnik do funkcji wykonującej animację)
|
||||
*/
|
||||
std::vector<TAnim> pAnimations;
|
||||
TSubModel **
|
||||
pAnimated; // lista animowanych submodeli (może być ich więcej niż obiektów animujących)
|
||||
double dWheelAngle[3]; // kąty obrotu kół: 0=przednie toczne, 1=napędzające i wiązary, 2=tylne
|
||||
// toczne
|
||||
void
|
||||
UpdateNone(TAnim *pAnim){}; // animacja pusta (funkcje ustawiania submodeli, gdy blisko kamery)
|
||||
TSubModel ** pAnimated; // lista animowanych submodeli (może być ich więcej niż obiektów animujących)
|
||||
double dWheelAngle[3]; // kąty obrotu kół: 0=przednie toczne, 1=napędzające i wiązary, 2=tylne toczne
|
||||
void UpdateNone(TAnim *pAnim){}; // animacja pusta (funkcje ustawiania submodeli, gdy blisko kamery)
|
||||
void UpdateAxle(TAnim *pAnim); // animacja osi
|
||||
void UpdateBoogie(TAnim *pAnim); // animacja wózka
|
||||
void UpdateDoorTranslate(TAnim *pAnim); // animacja drzwi - przesuw
|
||||
@@ -268,8 +264,7 @@ public: // modele składowe pojazdu
|
||||
|
||||
TButton btCoupler1; // sprzegi
|
||||
TButton btCoupler2;
|
||||
TAirCoupler
|
||||
btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
|
||||
TAirCoupler btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
|
||||
TAirCoupler btCPneumatic2;
|
||||
TAirCoupler btCPneumatic1r; // ABu: to zeby nie bylo problemow przy laczeniu wagonow,
|
||||
TAirCoupler btCPneumatic2r; // jesli beda polaczone sprzegami 1<->1 lub 0<->0
|
||||
@@ -300,8 +295,6 @@ public: // modele składowe pojazdu
|
||||
TButton btHeadSignals23;
|
||||
TButton btMechanik1;
|
||||
TButton btMechanik2;
|
||||
//TSubModel *smMechanik0; // Ra: mechanik wbudowany w model jako submodel?
|
||||
//TSubModel *smMechanik1; // mechanik od strony sprzęgu 1
|
||||
double enginevolume; // MC: pomocnicze zeby gladziej silnik buczal
|
||||
|
||||
int iAxles; // McZapkie: to potem mozna skasowac i zastapic iNumAxles
|
||||
@@ -325,7 +318,6 @@ public: // modele składowe pojazdu
|
||||
TAdvancedSound sReleaser;
|
||||
|
||||
// Winger 010304
|
||||
// TRealSound rsPanTup; //PSound sPantUp;
|
||||
TRealSound sPantUp;
|
||||
TRealSound sPantDown;
|
||||
TRealSound rsDoorOpen; // Ra: przeniesione z kabiny
|
||||
@@ -352,8 +344,6 @@ public: // modele składowe pojazdu
|
||||
int iHornWarning; // numer syreny do użycia po otrzymaniu sygnału do jazdy
|
||||
bool bEnabled; // Ra: wyjechał na portal i ma być usunięty
|
||||
protected:
|
||||
// TTrackFollower Axle2; //dwie osie z czterech (te są protected)
|
||||
// TTrackFollower Axle3; //Ra: wyłączyłem, bo kąty są liczone w Segment.cpp
|
||||
int iNumAxles; // ilość osi
|
||||
std::string asModel;
|
||||
|
||||
@@ -373,26 +363,18 @@ public: // modele składowe pojazdu
|
||||
TDynamicObject * PrevC(int C);
|
||||
TDynamicObject * NextC(int C);
|
||||
double NextDistance(double d = -1.0);
|
||||
void SetdMoveLen(double dMoveLen)
|
||||
{
|
||||
MoverParameters->dMoveLen = dMoveLen;
|
||||
}
|
||||
void ResetdMoveLen()
|
||||
{
|
||||
MoverParameters->dMoveLen = 0;
|
||||
}
|
||||
double GetdMoveLen()
|
||||
{
|
||||
return MoverParameters->dMoveLen;
|
||||
}
|
||||
void SetdMoveLen(double dMoveLen) {
|
||||
MoverParameters->dMoveLen = dMoveLen; }
|
||||
void ResetdMoveLen() {
|
||||
MoverParameters->dMoveLen = 0; }
|
||||
double GetdMoveLen() {
|
||||
return MoverParameters->dMoveLen; }
|
||||
|
||||
int GetPneumatic(bool front, bool red);
|
||||
void SetPneumatic(bool front, bool red);
|
||||
std::string asName;
|
||||
std::string GetName()
|
||||
{
|
||||
return this ? asName : std::string("");
|
||||
};
|
||||
std::string name() const {
|
||||
return this ? asName : std::string(); };
|
||||
|
||||
TRealSound rsDiesielInc; // youBy
|
||||
TRealSound rscurve; // youBy
|
||||
@@ -405,7 +387,6 @@ public: // modele składowe pojazdu
|
||||
TDynamicObject * ABuScanNearestObject(TTrack *Track, double ScanDir, double ScanDist,
|
||||
int &CouplNr);
|
||||
TDynamicObject * GetFirstDynamic(int cpl_type, int cf = 1);
|
||||
// TDynamicObject* GetFirstCabDynamic(int cpl_type);
|
||||
void ABuSetModelShake( Math3D::vector3 mShake);
|
||||
|
||||
// McZapkie-010302
|
||||
@@ -437,99 +418,65 @@ public: // modele składowe pojazdu
|
||||
void Move(double fDistance);
|
||||
void FastMove(double fDistance);
|
||||
void RenderSounds();
|
||||
inline Math3D::vector3 GetPosition() const
|
||||
{
|
||||
return vPosition;
|
||||
};
|
||||
inline Math3D::vector3 HeadPosition()
|
||||
{
|
||||
return vCoulpler[iDirection ^ 1];
|
||||
}; // pobranie współrzędnych czoła
|
||||
inline Math3D::vector3 RearPosition()
|
||||
{
|
||||
return vCoulpler[iDirection];
|
||||
}; // pobranie współrzędnych tyłu
|
||||
inline Math3D::vector3 AxlePositionGet()
|
||||
{
|
||||
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition;
|
||||
};
|
||||
inline Math3D::vector3 VectorFront() const
|
||||
{
|
||||
return vFront;
|
||||
};
|
||||
inline Math3D::vector3 VectorUp()
|
||||
{
|
||||
return vUp;
|
||||
};
|
||||
inline Math3D::vector3 VectorLeft() const
|
||||
{
|
||||
return vLeft;
|
||||
};
|
||||
inline double * Matrix()
|
||||
{
|
||||
return mMatrix.getArray();
|
||||
};
|
||||
inline double GetVelocity()
|
||||
{
|
||||
return MoverParameters->Vel;
|
||||
};
|
||||
inline double GetLength() const
|
||||
{
|
||||
return MoverParameters->Dim.L;
|
||||
};
|
||||
inline double GetWidth() const
|
||||
{
|
||||
return MoverParameters->Dim.W;
|
||||
};
|
||||
inline TTrack * GetTrack()
|
||||
{
|
||||
return (iAxleFirst ? Axle1.GetTrack() : Axle0.GetTrack());
|
||||
};
|
||||
// void UpdatePos();
|
||||
inline Math3D::vector3 GetPosition() const {
|
||||
return vPosition; };
|
||||
// pobranie współrzędnych czoła
|
||||
inline Math3D::vector3 HeadPosition() {
|
||||
return vCoulpler[iDirection ^ 1]; };
|
||||
// pobranie współrzędnych tyłu
|
||||
inline Math3D::vector3 RearPosition() {
|
||||
return vCoulpler[iDirection]; };
|
||||
inline Math3D::vector3 AxlePositionGet() {
|
||||
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition; };
|
||||
inline Math3D::vector3 VectorFront() const {
|
||||
return vFront; };
|
||||
inline Math3D::vector3 VectorUp() {
|
||||
return vUp; };
|
||||
inline Math3D::vector3 VectorLeft() const {
|
||||
return vLeft; };
|
||||
inline double * Matrix() {
|
||||
return mMatrix.getArray(); };
|
||||
inline double GetVelocity() {
|
||||
return MoverParameters->Vel; };
|
||||
inline double GetLength() const {
|
||||
return MoverParameters->Dim.L; };
|
||||
inline double GetWidth() const {
|
||||
return MoverParameters->Dim.W; };
|
||||
inline TTrack * GetTrack() {
|
||||
return (iAxleFirst ? Axle1.GetTrack() : Axle0.GetTrack()); };
|
||||
|
||||
// McZapkie-260202
|
||||
void LoadMMediaFile(std::string BaseDir, std::string TypeName, std::string ReplacableSkin);
|
||||
|
||||
inline double ABuGetDirection() const // ABu.
|
||||
{
|
||||
return (Axle1.GetTrack() == MyTrack ? Axle1.GetDirection() : Axle0.GetDirection());
|
||||
};
|
||||
// inline double ABuGetTranslation() //ABu.
|
||||
// {//zwraca przesunięcie wózka względem Point1 toru
|
||||
// return (Axle1.GetTrack()==MyTrack?Axle1.GetTranslation():Axle0.GetTranslation());
|
||||
// };
|
||||
inline double RaDirectionGet()
|
||||
{ // zwraca kierunek pojazdu na torze z aktywną osą
|
||||
return iAxleFirst ? Axle1.GetDirection() : Axle0.GetDirection();
|
||||
};
|
||||
inline double RaTranslationGet()
|
||||
{ // zwraca przesunięcie wózka względem Point1 toru z aktywną osią
|
||||
return iAxleFirst ? Axle1.GetTranslation() : Axle0.GetTranslation();
|
||||
};
|
||||
inline TTrack * RaTrackGet()
|
||||
{ // zwraca tor z aktywną osią
|
||||
return iAxleFirst ? Axle1.GetTrack() : Axle0.GetTrack();
|
||||
};
|
||||
inline double ABuGetDirection() const { // ABu.
|
||||
return (Axle1.GetTrack() == MyTrack ? Axle1.GetDirection() : Axle0.GetDirection()); };
|
||||
// zwraca kierunek pojazdu na torze z aktywną osą
|
||||
inline double RaDirectionGet() {
|
||||
return iAxleFirst ? Axle1.GetDirection() : Axle0.GetDirection(); };
|
||||
// zwraca przesunięcie wózka względem Point1 toru z aktywną osią
|
||||
inline double RaTranslationGet() {
|
||||
return iAxleFirst ? Axle1.GetTranslation() : Axle0.GetTranslation(); };
|
||||
// zwraca tor z aktywną osią
|
||||
inline TTrack * RaTrackGet() {
|
||||
return iAxleFirst ? Axle1.GetTrack() : Axle0.GetTrack(); };
|
||||
void CouplersDettach(double MinDist, int MyScanDir);
|
||||
void RadioStop();
|
||||
void Damage(char flag);
|
||||
void RaLightsSet(int head, int rear);
|
||||
// void RaAxleEvent(TEvent *e);
|
||||
TDynamicObject * FirstFind(int &coupler_nr, int cf = 1);
|
||||
float GetEPP(); // wyliczanie sredniego cisnienia w PG
|
||||
int DirectionSet(int d); // ustawienie kierunku w składzie
|
||||
int DirectionGet()
|
||||
{
|
||||
return iDirection + iDirection - 1;
|
||||
}; // odczyt kierunku w składzie
|
||||
// odczyt kierunku w składzie
|
||||
int DirectionGet() {
|
||||
return iDirection + iDirection - 1; };
|
||||
int DettachStatus(int dir);
|
||||
int Dettach(int dir);
|
||||
TDynamicObject * Neightbour(int &dir);
|
||||
void CoupleDist();
|
||||
TDynamicObject * ControlledFind();
|
||||
void ParamSet(int what, int into);
|
||||
int RouteWish(TTrack *tr); // zapytanie do AI, po którym segmencie skrzyżowania
|
||||
// jechać
|
||||
// zapytanie do AI, po którym segmencie skrzyżowania jechać
|
||||
int RouteWish(TTrack *tr);
|
||||
void DestinationSet(std::string to, std::string numer);
|
||||
std::string TextureTest(std::string const &name);
|
||||
void OverheadTrack(float o);
|
||||
@@ -537,4 +484,14 @@ public: // modele składowe pojazdu
|
||||
static std::string const MED_labels[ 8 ];
|
||||
};
|
||||
|
||||
|
||||
|
||||
class vehicle_table : public basic_table<TDynamicObject> {
|
||||
|
||||
public:
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
update( double dt, int iter );
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
202
Event.cpp
202
Event.cpp
@@ -74,10 +74,6 @@ TEvent::~TEvent() {
|
||||
|
||||
};
|
||||
|
||||
void TEvent::Init(){
|
||||
|
||||
};
|
||||
|
||||
void TEvent::Conditions(cParser *parser, std::string s)
|
||||
{ // przetwarzanie warunków, wspólne dla Multiple i UpdateValues
|
||||
if (s == "condition")
|
||||
@@ -949,7 +945,7 @@ event_manager::CheckQuery() {
|
||||
// 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->GetName() );
|
||||
WyslijEvent( tmpEvent->asName, tmpEvent->Activator->name() );
|
||||
}
|
||||
*/
|
||||
m_workevent->Params[ 9 ].asMemCell->PutCommand(
|
||||
@@ -984,61 +980,105 @@ event_manager::CheckQuery() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tp_Lights:
|
||||
if (m_workevent->Params[9].asModel)
|
||||
for (i = 0; i < iMaxNumLights; i++)
|
||||
if (m_workevent->Params[i].asdouble >= 0) //-1 zostawia bez zmiany
|
||||
case tp_Lights: {
|
||||
if( m_workevent->Params[ 9 ].asModel ) {
|
||||
for( i = 0; i < iMaxNumLights; ++i ) {
|
||||
if( m_workevent->Params[ i ].asdouble >= 0 ) {
|
||||
// -1 zostawia bez zmiany
|
||||
m_workevent->Params[ 9 ].asModel->LightSet(
|
||||
i, m_workevent->Params[i].asdouble); // teraz też ułamek
|
||||
i,
|
||||
m_workevent->Params[ i ].asdouble );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tp_Visible:
|
||||
}
|
||||
case tp_Visible: {
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
if( m_workevent->Params[ 9 ].nGroundNode )
|
||||
m_workevent->Params[ 9 ].nGroundNode->bVisible = ( m_workevent->Params[ i ].asInt > 0 );
|
||||
#else
|
||||
if( m_workevent->Params[ 9 ].asEditorNode )
|
||||
m_workevent->Params[ 9 ].asEditorNode->visible( m_workevent->Params[ i ].asInt > 0 );
|
||||
#endif
|
||||
break;
|
||||
case tp_Velocity:
|
||||
}
|
||||
case tp_Velocity: {
|
||||
Error( "Not implemented yet :(" );
|
||||
break;
|
||||
case tp_Exit:
|
||||
}
|
||||
case tp_Exit: {
|
||||
MessageBox( 0, m_workevent->asNodeName.c_str(), " THE END ", MB_OK );
|
||||
Global::iTextMode = -1; // wyłączenie takie samo jak sekwencja F10 -> Y
|
||||
return false;
|
||||
case tp_Sound:
|
||||
switch (m_workevent->Params[0].asInt)
|
||||
{ // trzy możliwe przypadki:
|
||||
case 0:
|
||||
}
|
||||
case tp_Sound: {
|
||||
switch( m_workevent->Params[ 0 ].asInt ) {
|
||||
// trzy możliwe przypadki:
|
||||
case 0: {
|
||||
m_workevent->Params[ 9 ].tsTextSound->Stop();
|
||||
break;
|
||||
case 1:
|
||||
}
|
||||
case 1: {
|
||||
m_workevent->Params[ 9 ].tsTextSound->Play(
|
||||
1, 0, true, m_workevent->Params[9].tsTextSound->vSoundPosition);
|
||||
break;
|
||||
case -1:
|
||||
m_workevent->Params[9].tsTextSound->Play(
|
||||
1, DSBPLAY_LOOPING, true, m_workevent->Params[9].tsTextSound->vSoundPosition);
|
||||
1,
|
||||
0,
|
||||
true,
|
||||
m_workevent->Params[ 9 ].tsTextSound->vSoundPosition );
|
||||
break;
|
||||
}
|
||||
case -1: {
|
||||
m_workevent->Params[ 9 ].tsTextSound->Play(
|
||||
1,
|
||||
DSBPLAY_LOOPING,
|
||||
true,
|
||||
m_workevent->Params[ 9 ].tsTextSound->vSoundPosition );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tp_Disable:
|
||||
Error("Not implemented yet :(");
|
||||
break;
|
||||
case tp_Animation: // Marcin: dorobic translacje - Ra: dorobiłem ;-)
|
||||
if (m_workevent->Params[0].asInt == 1)
|
||||
case tp_Animation: {
|
||||
switch( m_workevent->Params[ 0 ].asInt ) {
|
||||
case 1: {
|
||||
m_workevent->Params[ 9 ].asAnimContainer->SetRotateAnim(
|
||||
Math3D::vector3(m_workevent->Params[1].asdouble, m_workevent->Params[2].asdouble,
|
||||
m_workevent->Params[3].asdouble),
|
||||
Math3D::vector3 {
|
||||
m_workevent->Params[ 1 ].asdouble,
|
||||
m_workevent->Params[ 2 ].asdouble,
|
||||
m_workevent->Params[ 3 ].asdouble },
|
||||
m_workevent->Params[ 4 ].asdouble );
|
||||
else if (m_workevent->Params[0].asInt == 2)
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
m_workevent->Params[ 9 ].asAnimContainer->SetTranslateAnim(
|
||||
Math3D::vector3(m_workevent->Params[1].asdouble, m_workevent->Params[2].asdouble,
|
||||
m_workevent->Params[3].asdouble),
|
||||
Math3D::vector3 {
|
||||
m_workevent->Params[ 1 ].asdouble,
|
||||
m_workevent->Params[ 2 ].asdouble,
|
||||
m_workevent->Params[ 3 ].asdouble },
|
||||
m_workevent->Params[ 4 ].asdouble );
|
||||
else if (m_workevent->Params[0].asInt == 4)
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
m_workevent->Params[ 9 ].asModel->AnimationVND(
|
||||
m_workevent->Params[ 8 ].asPointer,
|
||||
m_workevent->Params[ 1 ].asdouble, // tu mogą być dodatkowe parametry, np. od-do
|
||||
m_workevent->Params[2].asdouble, m_workevent->Params[3].asdouble,
|
||||
m_workevent->Params[ 2 ].asdouble,
|
||||
m_workevent->Params[ 3 ].asdouble,
|
||||
m_workevent->Params[ 4 ].asdouble );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tp_Switch: {
|
||||
if( m_workevent->Params[ 9 ].asTrack ) {
|
||||
m_workevent->Params[ 9 ].asTrack->Switch(
|
||||
@@ -1057,13 +1097,15 @@ event_manager::CheckQuery() {
|
||||
break;
|
||||
}
|
||||
case tp_TrackVel:
|
||||
if (m_workevent->Params[9].asTrack)
|
||||
{ // prędkość na zwrotnicy może być ograniczona z góry we wpisie, większej się nie
|
||||
// ustawi eventem
|
||||
WriteLog("Type: TrackVel");
|
||||
if (m_workevent->Params[9].asTrack) {
|
||||
// prędkość na zwrotnicy może być ograniczona z góry we wpisie, większej się nie ustawi eventem
|
||||
m_workevent->Params[9].asTrack->VelocitySet(m_workevent->Params[0].asdouble);
|
||||
if (DebugModeFlag) // wyświetlana jest ta faktycznie ustawiona
|
||||
WriteLog(" - velocity: ", m_workevent->Params[9].asTrack->VelocityGet());
|
||||
// wyświetlana jest ta faktycznie ustawiona
|
||||
WriteLog( "Type: TrackVel - ["
|
||||
+ to_string( m_workevent->Params[ 0 ].asdouble, 2 ) + "]"
|
||||
+ ( DebugModeFlag ?
|
||||
", actual [ " + to_string( m_workevent->Params[ 9 ].asTrack->VelocityGet(), 2 ) + "]" :
|
||||
"" ) );
|
||||
}
|
||||
break;
|
||||
case tp_DynVel:
|
||||
@@ -1097,7 +1139,7 @@ event_manager::CheckQuery() {
|
||||
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->GetName() );
|
||||
WyslijEvent( m_workevent->asName, m_workevent->Activator->name() );
|
||||
}
|
||||
else {
|
||||
WyslijEvent( m_workevent->asName, "" );
|
||||
@@ -1175,7 +1217,8 @@ event_manager::CheckQuery() {
|
||||
m_workevent->Params[ 9 ].asMemCell->UpdateValues(
|
||||
m_workevent->Activator->Mechanik->TrainName(),
|
||||
m_workevent->Activator->Mechanik->StationCount() - m_workevent->Activator->Mechanik->StationIndex(), // ile przystanków do końca
|
||||
m_workevent->Activator->Mechanik->IsStop() ? 1 :
|
||||
m_workevent->Activator->Mechanik->IsStop() ?
|
||||
1 :
|
||||
0, // 1, gdy ma tu zatrzymanie
|
||||
m_workevent->iFlags);
|
||||
WriteLog("Train detected: " + m_workevent->Activator->Mechanik->TrainName());
|
||||
@@ -1186,10 +1229,10 @@ event_manager::CheckQuery() {
|
||||
// zapisanie zawartości komórki pamięci do logu
|
||||
if( m_workevent->Params[ 9 ].asMemCell ) {
|
||||
// jeśli była podana nazwa komórki
|
||||
WriteLog( "Memcell \"" + m_workevent->asNodeName + "\": "
|
||||
+ m_workevent->Params[ 9 ].asMemCell->Text() + " "
|
||||
+ std::to_string( m_workevent->Params[ 9 ].asMemCell->Value1() ) + " "
|
||||
+ std::to_string( m_workevent->Params[ 9 ].asMemCell->Value2() ) );
|
||||
WriteLog( "Memcell \"" + m_workevent->asNodeName + "\": ["
|
||||
+ m_workevent->Params[ 9 ].asMemCell->Text() + "] ["
|
||||
+ to_string( m_workevent->Params[ 9 ].asMemCell->Value1(), 2 ) + "] ["
|
||||
+ to_string( m_workevent->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" );
|
||||
}
|
||||
else {
|
||||
// TODO: re-enable when cell manager is in place
|
||||
@@ -1237,7 +1280,7 @@ event_manager::InitEvents() {
|
||||
case tp_AddValues: // sumowanie wartości
|
||||
case tp_UpdateValues: { // zmiana wartości
|
||||
auto *cell = simulation::Memory.find( Current->asNodeName ); // nazwa komórki powiązanej z eventem
|
||||
if( cell ) { // McZapkie-100302
|
||||
if( cell != nullptr ) { // McZapkie-100302
|
||||
if( Current->iFlags & ( conditional_trackoccupied | conditional_trackfree ) ) {
|
||||
// jeśli chodzi o zajetosc toru (tor może być inny, niż wpisany w komórce)
|
||||
// nazwa toru ta sama, co nazwa komórki
|
||||
@@ -1281,7 +1324,7 @@ event_manager::InitEvents() {
|
||||
case tp_GetValues:
|
||||
case tp_WhoIs: {
|
||||
auto *cell = simulation::Memory.find( Current->asNodeName );
|
||||
if( cell ) {
|
||||
if( cell != nullptr ) {
|
||||
Current->Params[ 8 ].asLocation = &( cell->location() );
|
||||
Current->Params[ 9 ].asMemCell = cell;
|
||||
if( ( Current->Type == tp_GetValues )
|
||||
@@ -1301,7 +1344,7 @@ event_manager::InitEvents() {
|
||||
case tp_CopyValues: {
|
||||
// skopiowanie komórki do innej
|
||||
auto *cell = simulation::Memory.find( Current->asNodeName ); // komórka docelowa
|
||||
if( cell ) {
|
||||
if( cell != nullptr ) {
|
||||
Current->Params[ 4 ].asLocation = &( cell->location() );
|
||||
Current->Params[ 5 ].asMemCell = cell; // komórka docelowa
|
||||
if( false == cell->asTrackName.empty() ) {
|
||||
@@ -1338,7 +1381,7 @@ event_manager::InitEvents() {
|
||||
SafeDeleteArray( Current->Params[ 9 ].asText );
|
||||
// egzemplarz modelu do animowania
|
||||
auto *instance = simulation::Instances.find( Current->asNodeName );
|
||||
if( instance ) {
|
||||
if( instance != nullptr ) {
|
||||
if( Current->Params[ 0 ].asInt == 4 ) {
|
||||
// model dla całomodelowych animacji
|
||||
Current->Params[ 9 ].asModel = instance;
|
||||
@@ -1365,33 +1408,35 @@ event_manager::InitEvents() {
|
||||
case tp_Lights: {
|
||||
// zmiana świeteł modelu
|
||||
auto *instance = simulation::Instances.find( Current->asNodeName );
|
||||
if( instance )
|
||||
if( instance != nullptr )
|
||||
Current->Params[ 9 ].asModel = instance;
|
||||
else
|
||||
ErrorLog( "Bad event: lights event \"" + Current->asName + "\" cannot find model instance \"" + Current->asNodeName + "\"" );
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case tp_Visible: {
|
||||
// ukrycie albo przywrócenie obiektu
|
||||
tmp = FindGroundNode( Current->asNodeName, TP_MODEL ); // najpierw model
|
||||
if( !tmp )
|
||||
tmp = FindGroundNode( Current->asNodeName, TP_TRACK ); // albo tory?
|
||||
if( !tmp )
|
||||
tmp = FindGroundNode( Current->asNodeName, TP_TRACTION ); // może druty?
|
||||
if( tmp )
|
||||
Current->Params[ 9 ].nGroundNode = tmp;
|
||||
editor::basic_node *node = simulation::Instances.find( Current->asNodeName ); // najpierw model
|
||||
if( node == nullptr ) {
|
||||
// albo tory?
|
||||
node = simulation::Paths.find( Current->asNodeName );
|
||||
}
|
||||
if( node == nullptr ) {
|
||||
// może druty?
|
||||
node = simulation::Traction.find( Current->asNodeName );
|
||||
}
|
||||
if( node != nullptr )
|
||||
Current->Params[ 9 ].asEditorNode = node;
|
||||
else
|
||||
ErrorLog( "Bad event: visibility event \"" + Current->asName + "\" cannot find item \"" + Current->asNodeName + "\"" );
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case tp_Switch: {
|
||||
// przełożenie zwrotnicy albo zmiana stanu obrotnicy
|
||||
auto *track = simulation::Paths.find( Current->asNodeName );
|
||||
if( track ) {
|
||||
if( track != nullptr ) {
|
||||
// dowiązanie toru
|
||||
if( track->iAction == NULL ) {
|
||||
// jeśli nie jest zwrotnicą ani obrotnicą to będzie się zmieniał stan uszkodzenia
|
||||
@@ -1414,23 +1459,21 @@ event_manager::InitEvents() {
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case tp_Sound: {
|
||||
// odtworzenie dźwięku
|
||||
tmp = FindGroundNode( Current->asNodeName, TP_SOUND );
|
||||
if( tmp )
|
||||
Current->Params[ 9 ].tsTextSound = tmp->tsStaticSound;
|
||||
auto *sound = simulation::Sounds.find( Current->asNodeName );
|
||||
if( sound != nullptr )
|
||||
Current->Params[ 9 ].tsTextSound = sound;
|
||||
else
|
||||
ErrorLog( "Bad event: sound event \"" + Current->asName + "\" cannot find static sound \"" + Current->asNodeName + "\"" );
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case tp_TrackVel: {
|
||||
// ustawienie prędkości na torze
|
||||
if( false == Current->asNodeName.empty() ) {
|
||||
auto *track = simulation::Paths.find( Current->asNodeName );
|
||||
if( track ) {
|
||||
if( track != nullptr ) {
|
||||
// flaga zmiany prędkości toru jest istotna dla skanowania
|
||||
track->iAction |= 0x200;
|
||||
Current->Params[ 9 ].asTrack = track;
|
||||
@@ -1442,22 +1485,20 @@ event_manager::InitEvents() {
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case tp_DynVel: {
|
||||
// komunikacja z pojazdem o konkretnej nazwie
|
||||
if( Current->asNodeName == "activator" )
|
||||
Current->Params[ 9 ].asDynamic = nullptr;
|
||||
else {
|
||||
tmp = FindGroundNode( Current->asNodeName, TP_DYNAMIC );
|
||||
if( tmp )
|
||||
Current->Params[ 9 ].asDynamic = tmp->DynamicObject;
|
||||
auto *vehicle = simulation::Vehicles.find( Current->asNodeName );
|
||||
if( vehicle != nullptr )
|
||||
Current->Params[ 9 ].asDynamic = vehicle;
|
||||
else
|
||||
Error( "Bad event: vehicle velocity event \"" + Current->asName + "\" cannot find vehicle \"" + Current->asNodeName + "\"" );
|
||||
}
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case tp_Multiple: {
|
||||
std::string cellastext;
|
||||
if( Current->Params[ 9 ].asText != nullptr ) { // przepisanie nazwy do bufora
|
||||
@@ -1494,37 +1535,28 @@ event_manager::InitEvents() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case tp_Voltage: {
|
||||
// zmiana napięcia w zasilaczu (TractionPowerSource)
|
||||
if( !Current->asNodeName.empty() ) {
|
||||
tmp = FindGroundNode( Current->asNodeName, TP_TRACTIONPOWERSOURCE ); // podłączenie zasilacza
|
||||
if( tmp )
|
||||
Current->Params[ 9 ].psPower = tmp->psTractionPowerSource;
|
||||
if( false == Current->asNodeName.empty() ) {
|
||||
auto *powersource = simulation::Powergrid.find( Current->asNodeName ); // podłączenie zasilacza
|
||||
if( powersource != nullptr )
|
||||
Current->Params[ 9 ].psPower = powersource;
|
||||
else
|
||||
ErrorLog( "Bad event: voltage event \"" + Current->asName + "\" cannot find power source \"" + Current->asNodeName + "\"" );
|
||||
}
|
||||
Current->asNodeName = "";
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case tp_Message: {
|
||||
// wyświetlenie komunikatu
|
||||
break;
|
||||
}
|
||||
|
||||
} // switch
|
||||
if( Current->fDelay < 0 ) {
|
||||
AddToQuery( Current, nullptr );
|
||||
|
||||
if( Current->fDelay < 0 ) { AddToQuery( Current, nullptr ); }
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (TGroundNode *Current = nRootOfType[TP_MEMCELL]; Current; Current = Current->nNext)
|
||||
{ // Ra: eventy komórek pamięci, wykonywane po wysłaniu komendy do zatrzymanego pojazdu
|
||||
Current->MemCell->AssignEvents( FindEvent( Current->asName + ":sent" ) );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// legacy method, verifies condition for specified event
|
||||
bool
|
||||
|
||||
14
Event.h
14
Event.h
@@ -12,6 +12,9 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include <string>
|
||||
#include "dumb3d.h"
|
||||
#include "classes.h"
|
||||
#include "names.h"
|
||||
#include "scenenode.h"
|
||||
#include "evlaunch.h"
|
||||
|
||||
enum TEventType {
|
||||
tp_Unknown,
|
||||
@@ -61,6 +64,7 @@ union TParam
|
||||
void *asPointer;
|
||||
TMemCell *asMemCell;
|
||||
TGroundNode *nGroundNode;
|
||||
editor::basic_node *asEditorNode;
|
||||
glm::dvec3 const *asLocation;
|
||||
TTrack *asTrack;
|
||||
TAnimModel *asModel;
|
||||
@@ -104,7 +108,6 @@ public:
|
||||
// metody
|
||||
TEvent(std::string const &m = "");
|
||||
~TEvent();
|
||||
void Init();
|
||||
void Load(cParser *parser, Math3D::vector3 const &org);
|
||||
static void AddToQuery( TEvent *Event, TEvent *&Start );
|
||||
std::string CommandGet();
|
||||
@@ -123,9 +126,12 @@ public:
|
||||
~event_manager();
|
||||
// methods
|
||||
// adds provided event to the collection. returns: true on success
|
||||
// TODO: return handle instead of pointer
|
||||
// TBD, TODO: return handle to the event
|
||||
bool
|
||||
insert( TEvent *Event );
|
||||
bool
|
||||
insert( TEventLauncher *Launcher ) {
|
||||
return m_launchers.insert( Launcher ); }
|
||||
// legacy method, returns pointer to specified event, or null
|
||||
TEvent *
|
||||
FindEvent( std::string const &Name );
|
||||
@@ -143,6 +149,7 @@ private:
|
||||
// types
|
||||
using event_sequence = std::deque<TEvent *>;
|
||||
using event_map = std::unordered_map<std::string, std::size_t>;
|
||||
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
||||
|
||||
// methods
|
||||
// legacy method, verifies condition for specified event
|
||||
@@ -158,8 +165,9 @@ private:
|
||||
// legacy version of the above
|
||||
TEvent *QueryRootEvent { nullptr };
|
||||
TEvent *m_workevent { nullptr };
|
||||
|
||||
event_map m_eventmap;
|
||||
basic_table<TEventLauncher> m_launchers;
|
||||
eventlauncher_sequence m_launcherqueue;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
9
Gauge.h
9
Gauge.h
@@ -12,15 +12,14 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Classes.h"
|
||||
#include "sound.h"
|
||||
|
||||
typedef enum
|
||||
{ // typ ruchu
|
||||
enum TGaugeType {
|
||||
// typ ruchu
|
||||
gt_Unknown, // na razie nie znany
|
||||
gt_Rotate, // obrót
|
||||
gt_Move, // przesunięcie równoległe
|
||||
gt_Wiper, // obrót trzech kolejnych submodeli o ten sam kąt (np. wycieraczka, drzwi
|
||||
// harmonijkowe)
|
||||
gt_Wiper, // obrót trzech kolejnych submodeli o ten sam kąt (np. wycieraczka, drzwi harmonijkowe)
|
||||
gt_Digital // licznik cyfrowy, np. kilometrów
|
||||
} TGaugeType;
|
||||
};
|
||||
|
||||
// animowany wskaźnik, mogący przyjmować wiele stanów pośrednich
|
||||
class TGauge {
|
||||
|
||||
@@ -996,10 +996,12 @@ void Global::TrainDelete(TDynamicObject *d)
|
||||
pWorld->TrainDelete(d);
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *Global::DynamicNearest()
|
||||
{ // ustalenie pojazdu najbliższego kamerze
|
||||
return pGround->DynamicNearest(pCamera->Pos);
|
||||
};
|
||||
#endif
|
||||
|
||||
TDynamicObject *Global::CouplerNearest()
|
||||
{ // ustalenie pojazdu najbliższego kamerze
|
||||
|
||||
@@ -297,7 +297,9 @@ class Global
|
||||
static void TrainDelete(TDynamicObject *d);
|
||||
static void ConfigParse(cParser &parser);
|
||||
static std::string GetNextSymbol();
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
static TDynamicObject * DynamicNearest();
|
||||
#endif
|
||||
static TDynamicObject * CouplerNearest();
|
||||
static bool AddToQuery(TEvent *event, TDynamicObject *who);
|
||||
static bool DoEvents();
|
||||
|
||||
185
Ground.cpp
185
Ground.cpp
@@ -586,7 +586,7 @@ void TGround::Free()
|
||||
// RootNode=NULL;
|
||||
nRootDynamic = NULL;
|
||||
}
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TGroundNode * TGround::DynamicFindAny(std::string const &Name)
|
||||
{ // wyszukanie pojazdu o podanej nazwie, szukanie po wszystkich (użyć drzewa!)
|
||||
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
||||
@@ -603,7 +603,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ę
|
||||
@@ -694,6 +694,7 @@ int iTrainSetWehicleNumber = 0;
|
||||
TGroundNode *nTrainSetNode = NULL; // poprzedni pojazd do łączenia
|
||||
TGroundNode *nTrainSetDriver = NULL; // pojazd, któremu zostanie wysłany rozkład
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void TGround::RaTriangleDivider(TGroundNode *node)
|
||||
{ // tworzy dodatkowe trójkąty i zmiejsza podany
|
||||
// to jest wywoływane przy wczytywaniu trójkątów
|
||||
@@ -814,7 +815,7 @@ void TGround::RaTriangleDivider(TGroundNode *node)
|
||||
RaTriangleDivider(node); // rekurencja, bo nawet na TD raz nie wystarczy
|
||||
RaTriangleDivider(ntri);
|
||||
};
|
||||
|
||||
#endif
|
||||
TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
{ // wczytanie wpisu typu "node"
|
||||
std::string str, str1, str2, str3, str4, Skin, DriverType, asNodeName;
|
||||
@@ -889,6 +890,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
|
||||
switch (tmp->iType)
|
||||
{
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
case TP_TRACTION:
|
||||
tmp->hvTraction = new TTraction( tmp->asName );
|
||||
parser->getTokens();
|
||||
@@ -983,7 +985,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
>> tmp->pCenter.y
|
||||
>> tmp->pCenter.z;
|
||||
tmp->pCenter += pOrigin;
|
||||
tmp->psTractionPowerSource = new TTractionPowerSource(tmp);
|
||||
tmp->psTractionPowerSource = new TTractionPowerSource( tmp->asName );
|
||||
tmp->psTractionPowerSource->Load(parser);
|
||||
break;
|
||||
case TP_MEMCELL:
|
||||
@@ -1004,6 +1006,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case TP_EVLAUNCH:
|
||||
parser->getTokens(3);
|
||||
*parser
|
||||
@@ -1015,6 +1018,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
tmp->EvLaunch = new TEventLauncher();
|
||||
tmp->EvLaunch->Load(parser);
|
||||
break;
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
case TP_TRACK:
|
||||
tmp->pTrack = new TTrack( tmp->asName );
|
||||
if (Global::iWriteLogEnabled & 4)
|
||||
@@ -1191,57 +1195,8 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
case TP_MODEL: {
|
||||
#ifdef EU07_USE_OLD_TERRAINCODE
|
||||
if( rmin < 0 ) {
|
||||
tmp->iType = TP_TERRAIN;
|
||||
tmp->fSquareMinRadius = 0; // to w ogóle potrzebne?
|
||||
}
|
||||
parser->getTokens( 3 );
|
||||
*parser >> tmp->pCenter.x >> tmp->pCenter.y >> tmp->pCenter.z;
|
||||
parser->getTokens();
|
||||
*parser >> tf1;
|
||||
// OlO_EU&KAKISH-030103: obracanie punktow zaczepien w modelu
|
||||
tmp->pCenter.RotateY( aRotate.y / 180.0 * M_PI );
|
||||
// McZapkie-260402: model tez ma wspolrzedne wzgledne
|
||||
tmp->pCenter += pOrigin;
|
||||
|
||||
tmp->Model = new TAnimModel();
|
||||
tmp->Model->RaAnglesSet( aRotate.x, tf1 + aRotate.y, aRotate.z ); // dostosowanie do pochylania linii
|
||||
if( tmp->Model->Load( parser, tmp->iType == TP_TERRAIN ) ) {
|
||||
// wczytanie modelu, tekstury i stanu świateł...
|
||||
tmp->iFlags = tmp->Model->Flags() | 0x200; // ustalenie, czy przezroczysty; flaga usuwania
|
||||
}
|
||||
else if( tmp->iType != TP_TERRAIN ) { // model nie wczytał się - ignorowanie node
|
||||
delete tmp;
|
||||
tmp = NULL; // nie może być tu return
|
||||
break; // nie może być tu return?
|
||||
}
|
||||
if( tmp->iType == TP_TERRAIN ) { // jeśli model jest terenem, trzeba utworzyć dodatkowe obiekty
|
||||
// po wczytaniu model ma już utworzone DL albo VBO
|
||||
Global::pTerrainCompact = tmp->Model; // istnieje co najmniej jeden obiekt terenu
|
||||
tmp->pCenter = Math3D::vector3( 0.0, 0.0, 0.0 ); // enforce placement in the world center
|
||||
tmp->iCount = Global::pTerrainCompact->TerrainCount() + 1; // zliczenie submodeli
|
||||
tmp->nNode = new TGroundNode[ tmp->iCount ]; // sztuczne node dla kwadratów
|
||||
tmp->nNode[ 0 ].iType = TP_MODEL; // pierwszy zawiera model (dla delete)
|
||||
tmp->nNode[ 0 ].Model = Global::pTerrainCompact;
|
||||
tmp->nNode[ 0 ].iFlags = 0x200; // nie wyświetlany, ale usuwany
|
||||
for( int i = 1; i < tmp->iCount; ++i ) { // a reszta to submodele
|
||||
tmp->nNode[ i ].iType = TP_SUBMODEL;
|
||||
tmp->nNode[ i ].smTerrain = Global::pTerrainCompact->TerrainSquare( i - 1 );
|
||||
tmp->nNode[ i ].iFlags = 0x10; // nieprzezroczyste; nie usuwany
|
||||
tmp->nNode[ i ].bVisible = true;
|
||||
tmp->nNode[ i ].pCenter = tmp->pCenter; // nie przesuwamy w inne miejsce
|
||||
}
|
||||
}
|
||||
else if( !tmp->asName.empty() ) // jest pusta gdy "none"
|
||||
{ // dodanie do wyszukiwarki
|
||||
if( false == m_nodemap.Add( TP_MODEL, tmp->asName, tmp ) ) {
|
||||
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
||||
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
|
||||
}
|
||||
}
|
||||
#else
|
||||
if( rmin < 0 ) {
|
||||
// legacy leftover: special case, terrain provided as 3d model
|
||||
tmp->iType = TP_TERRAIN;
|
||||
@@ -1274,6 +1229,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
// regular 3d model
|
||||
parser->getTokens( 3 );
|
||||
*parser
|
||||
@@ -1304,10 +1260,11 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
// case TP_GEOMETRY :
|
||||
case GL_TRIANGLES:
|
||||
case GL_TRIANGLE_STRIP:
|
||||
@@ -1510,6 +1467,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
} // koniec wczytywania trójkątów
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case GL_LINES:
|
||||
case GL_LINE_STRIP:
|
||||
case GL_LINE_LOOP: {
|
||||
@@ -1859,8 +1817,7 @@ bool TGround::Init(std::string File)
|
||||
if (nTrainSetDriver) // pojazd, któremu zostanie wysłany rozkład
|
||||
{ // wysłanie komendy "Timetable" ustawia odpowiedni tryb jazdy
|
||||
nTrainSetDriver->DynamicObject->Mechanik->DirectionInitial();
|
||||
nTrainSetDriver->DynamicObject->Mechanik->PutCommand("Timetable:" + asTrainName,
|
||||
fTrainSetVel, 0, NULL);
|
||||
nTrainSetDriver->DynamicObject->Mechanik->PutCommand("Timetable:" + asTrainName, fTrainSetVel, 0, NULL);
|
||||
}
|
||||
}
|
||||
if( LastNode ) {
|
||||
@@ -1926,7 +1883,7 @@ bool TGround::Init(std::string File)
|
||||
{
|
||||
ErrorLog("Duplicated event: " + tmp->asName);
|
||||
found->Append(tmp); // doczepka (taki wirtualny multiple bez warunków)
|
||||
found->Type = tp_Ignored; // dezaktywacja pierwotnego - taka proteza na
|
||||
found->m_ignored = true; // dezaktywacja pierwotnego - taka proteza na
|
||||
// wsteczną zgodność
|
||||
// SafeDelete(tmp); //bezlitośnie usuwamy wszelkie duplikaty, żeby nie
|
||||
// zaśmiecać drzewka
|
||||
@@ -1938,7 +1895,7 @@ bool TGround::Init(std::string File)
|
||||
RootEvent = tmp;
|
||||
if (!found)
|
||||
{ // jeśli nazwa wystąpiła, to do kolejki i wyszukiwarki dodawany jest tylko pierwszy
|
||||
if( ( RootEvent->Type != tp_Ignored )
|
||||
if( ( RootEvent->m_ignored == false )
|
||||
&& ( RootEvent->asName.find( "onstart" ) != std::string::npos ) ) {
|
||||
// event uruchamiany automatycznie po starcie
|
||||
AddToQuery( RootEvent, NULL ); // dodanie do kolejki
|
||||
@@ -2217,7 +2174,7 @@ bool TGround::InitEvents()
|
||||
}
|
||||
else
|
||||
{ // nie ma komórki, to nie będzie działał poprawnie
|
||||
Current->Type = tp_Ignored; // deaktywacja
|
||||
Current->m_ignored = true; // deaktywacja
|
||||
ErrorLog("Bad event: event \"" + Current->asName + "\" cannot find memcell \"" + Current->asNodeName + "\"");
|
||||
}
|
||||
break;
|
||||
@@ -2241,7 +2198,7 @@ bool TGround::InitEvents()
|
||||
}
|
||||
else
|
||||
{ // nie ma komórki, to nie będzie działał poprawnie
|
||||
Current->Type = tp_Ignored; // deaktywacja
|
||||
Current->m_ignored = true; // deaktywacja
|
||||
ErrorLog("Bad event: event \"" + Current->asName + "\" cannot find memcell \"" + Current->asNodeName + "\"");
|
||||
}
|
||||
break;
|
||||
@@ -2637,7 +2594,7 @@ void TGround::InitTraction()
|
||||
nTemp = new TGroundNode();
|
||||
nTemp->iType = TP_TRACTIONPOWERSOURCE;
|
||||
nTemp->asName = Traction->asPowerSupplyName;
|
||||
nTemp->psTractionPowerSource = new TTractionPowerSource(nTemp);
|
||||
nTemp->psTractionPowerSource = new TTractionPowerSource(nTemp->asName);
|
||||
nTemp->psTractionPowerSource->Init(Traction->NominalVoltage, Traction->MaxCurrent);
|
||||
nTemp->nNext = nRootOfType[nTemp->iType]; // ostatni dodany dołączamy na końcu
|
||||
// nowego
|
||||
@@ -2826,8 +2783,11 @@ void TGround::TrackJoin(TGroundNode *Current)
|
||||
int iConnection;
|
||||
if (!Track->CurrentPrev())
|
||||
{
|
||||
tmp = FindTrack(Track->CurrentSegment()->FastGetPoint_0(), iConnection,
|
||||
Current); // Current do pominięcia
|
||||
#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:
|
||||
@@ -2840,7 +2800,11 @@ 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:
|
||||
@@ -2892,6 +2856,7 @@ bool TGround::InitLaunchers()
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TTrack * TGround::FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude)
|
||||
{ // wyszukiwanie innego toru kończącego się w (Point)
|
||||
TTrack *tmp;
|
||||
@@ -2978,49 +2943,36 @@ TTraction * TGround::TractionNearestFind(glm::dvec3 &p, int dir, TGroundNode *n)
|
||||
if ((sr = FastGetSubRect(c + i, r + j)) != NULL) // o ile w ogóle sektor jest
|
||||
for (nCurrent = sr->nRenderWires; nCurrent; nCurrent = nCurrent->nNext3)
|
||||
if (nCurrent->iType == TP_TRACTION)
|
||||
if (nCurrent->hvTraction->psSection ==
|
||||
n->hvTraction->psSection) // jeśli ta sama sekcja
|
||||
if (nCurrent->hvTraction->psSection == n->hvTraction->psSection) // jeśli ta sama sekcja
|
||||
if (nCurrent != n) // ale nie jest tym samym
|
||||
if (nCurrent->hvTraction !=
|
||||
n->hvTraction
|
||||
->hvNext[0]) // ale nie jest bezpośrednio podłączonym
|
||||
if (nCurrent->hvTraction != n->hvTraction->hvNext[0]) // ale nie jest bezpośrednio podłączonym
|
||||
if (nCurrent->hvTraction != n->hvTraction->hvNext[1])
|
||||
if (nCurrent->hvTraction->psPower
|
||||
[k = (glm::dot(
|
||||
n->hvTraction->vParametric,
|
||||
nCurrent->hvTraction->vParametric) >= 0 ?
|
||||
dir ^ 1 :
|
||||
dir)]) // ma zasilanie z odpowiedniej
|
||||
// strony
|
||||
if (nCurrent->hvTraction->fResistance[k] >=
|
||||
0.0) //żeby się nie propagowały jakieś ujemne
|
||||
{ // znaleziony kandydat do połączenia
|
||||
dir)]) // ma zasilanie z odpowiedniej strony
|
||||
if (nCurrent->hvTraction->fResistance[k] >= 0.0) { // żeby się nie propagowały jakieś ujemne
|
||||
// znaleziony kandydat do połączenia
|
||||
d = glm::length2( p - glm::dvec3{ nCurrent->pCenter } ); // kwadrat odległości środków
|
||||
if (dist > d)
|
||||
{ // zapamiętanie nowego najbliższego
|
||||
if (dist > d) {
|
||||
// zapamiętanie nowego najbliższego
|
||||
dist = d; // nowy rekord odległości
|
||||
nBest = nCurrent;
|
||||
zg = k; // z którego końca brać wskaźnik
|
||||
// zasilacza
|
||||
zg = k; // z którego końca brać wskaźnik zasilacza
|
||||
}
|
||||
}
|
||||
if (nBest) // jak znalezione przęsło z zasilaniem, to podłączenie "równoległe"
|
||||
{
|
||||
n->hvTraction->ResistanceCalc(dir, nBest->hvTraction->fResistance[zg],
|
||||
nBest->hvTraction->psPower[zg]);
|
||||
// testowo skrzywienie przęsła tak, aby pokazać skąd ma zasilanie
|
||||
// if (dir) //1 gdy ciąg dalszy jest od strony Point2
|
||||
// n->hvTraction->pPoint3=0.25*(nBest->pCenter+3*(zg?nBest->hvTraction->pPoint4:nBest->hvTraction->pPoint3));
|
||||
// else
|
||||
// n->hvTraction->pPoint4=0.25*(nBest->pCenter+3*(zg?nBest->hvTraction->pPoint4:nBest->hvTraction->pPoint3));
|
||||
if (nBest) {
|
||||
// jak znalezione przęsło z zasilaniem, to podłączenie "równoległe"
|
||||
n->hvTraction->ResistanceCalc(dir, nBest->hvTraction->fResistance[zg], nBest->hvTraction->psPower[zg]);
|
||||
}
|
||||
return (nBest ? nBest->hvTraction : nullptr);
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
bool TGround::AddToQuery(TEvent *Event, TDynamicObject *Node)
|
||||
{
|
||||
if( Event->bEnabled ) {
|
||||
if( ( false == Event->m_ignored ) && ( true == Event->bEnabled ) ) {
|
||||
// jeśli może być dodany do kolejki (nie używany w skanowaniu)
|
||||
if( !Event->iQueued ) // jeśli nie dodany jeszcze do kolejki
|
||||
{ // kolejka eventów jest posortowana względem (fStartTime)
|
||||
@@ -3169,8 +3121,8 @@ bool TGround::CheckQuery()
|
||||
}
|
||||
else // a jak nazwa jest unikalna, to kolejka idzie dalej
|
||||
QueryRootEvent = QueryRootEvent->evNext; // NULL w skrajnym przypadku
|
||||
if (tmpEvent->bEnabled)
|
||||
{ // w zasadzie te wyłączone są skanowane i nie powinny się nigdy w kolejce znaleźć
|
||||
if( ( false == tmpEvent->m_ignored ) && ( true == tmpEvent->bEnabled ) ) {
|
||||
// w zasadzie te wyłączone są skanowane i nie powinny się nigdy w kolejce znaleźć
|
||||
--tmpEvent->iQueued; // teraz moze być ponownie dodany do kolejki
|
||||
WriteLog( "EVENT LAUNCHED" + ( tmpEvent->Activator ? ( " by " + tmpEvent->Activator->asName ) : "" ) + ": " + tmpEvent->asName );
|
||||
switch (tmpEvent->Type)
|
||||
@@ -3222,7 +3174,7 @@ bool TGround::CheckQuery()
|
||||
// loc.Z= tmpEvent->Params[8].nGroundNode->pCenter.y;
|
||||
if (Global::iMultiplayer) // potwierdzenie wykonania dla serwera (odczyt
|
||||
// semafora już tak nie działa)
|
||||
WyslijEvent(tmpEvent->asName, tmpEvent->Activator->GetName());
|
||||
WyslijEvent(tmpEvent->asName, tmpEvent->Activator->name());
|
||||
// tmpEvent->Params[9].asMemCell->PutCommand(tmpEvent->Activator->Mechanik,loc);
|
||||
tmpEvent->Params[9].asMemCell->PutCommand(
|
||||
tmpEvent->Activator->Mechanik, &tmpEvent->Params[8].nGroundNode->pCenter);
|
||||
@@ -3355,7 +3307,7 @@ bool TGround::CheckQuery()
|
||||
0) // jednoznaczne tylko, gdy nie było else
|
||||
{
|
||||
if (tmpEvent->Activator)
|
||||
WyslijEvent(tmpEvent->asName, tmpEvent->Activator->GetName());
|
||||
WyslijEvent(tmpEvent->asName, tmpEvent->Activator->name());
|
||||
else
|
||||
WyslijEvent(tmpEvent->asName, "");
|
||||
}
|
||||
@@ -3468,7 +3420,6 @@ bool TGround::CheckQuery()
|
||||
} // while
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TGround::UpdatePhys(double dt, int iter)
|
||||
{ // aktualizacja fizyki stałym krokiem: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń
|
||||
@@ -3587,9 +3538,8 @@ TGround::Update_Hidden() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// Winger 170204 - szukanie trakcji nad pantografami
|
||||
bool TGround::GetTraction(TDynamicObject *model)
|
||||
{ // aktualizacja drutu zasilającego dla każdego pantografu, żeby odczytać napięcie
|
||||
@@ -3709,35 +3659,29 @@ bool TGround::GetTraction(TDynamicObject *model)
|
||||
{ // dany sektor może nie mieć nic w środku
|
||||
for (node = tmp->nRenderWires; node;
|
||||
node = node->nNext3) // następny z grupy
|
||||
if (node->iType ==
|
||||
TP_TRACTION) // w grupie tej są druty oraz inne linie
|
||||
if (node->iType == TP_TRACTION) // w grupie tej są druty oraz inne linie
|
||||
{
|
||||
vParam =
|
||||
node->hvTraction
|
||||
->vParametric; // współczynniki równania parametrycznego
|
||||
// współczynniki równania parametrycznego
|
||||
vParam = node->hvTraction->vParametric;
|
||||
fRaParam = -glm::dot(pant0, vFront);
|
||||
auto const paramfrontdot = glm::dot( vParam, vFront );
|
||||
fRaParam =
|
||||
-( glm::dot( node->hvTraction->pPoint1, vFront ) + fRaParam )
|
||||
/ ( paramfrontdot != 0.0 ? paramfrontdot : 0.001 ); // div0 trap
|
||||
if ((fRaParam >= -0.001) ? (fRaParam <= 1.001) : false)
|
||||
{ // jeśli tylko jest w przedziale, wyznaczyć odległość wzdłuż
|
||||
// wektorów vUp i vLeft
|
||||
vStyk = node->hvTraction->pPoint1 +
|
||||
fRaParam * vParam; // punkt styku płaszczyzny z
|
||||
// drutem (dla generatora łuku
|
||||
// el.)
|
||||
vGdzie = vStyk - pant0; // wektor
|
||||
fVertical = glm::dot(
|
||||
vGdzie,
|
||||
vUp); // musi się mieścić w przedziale ruchu pantografu
|
||||
{ // jeśli tylko jest w przedziale, wyznaczyć odległość wzdłuż wektorów vUp i vLeft
|
||||
// punkt styku płaszczyzny z drutem (dla generatora łuku el.)
|
||||
vStyk = node->hvTraction->pPoint1 + fRaParam * vParam;
|
||||
// wektor musi się mieścić w przedziale ruchu pantografu
|
||||
vGdzie = vStyk - pant0;
|
||||
fVertical = glm::dot( vGdzie, vUp);
|
||||
if (fVertical >= 0.0) // jeśli ponad pantografem (bo może
|
||||
// łapać druty spod wiaduktu)
|
||||
if (Global::bEnableTraction ?
|
||||
fVertical < p->PantWys - 0.15 :
|
||||
false) // jeśli drut jest niżej niż 15cm pod
|
||||
// ślizgiem
|
||||
{ // przełączamy w tryb połamania, o ile jedzie;
|
||||
false) {
|
||||
// jeśli drut jest niżej niż 15cm pod ślizgiem
|
||||
// przełączamy w tryb połamania, o ile jedzie;
|
||||
// (bEnableTraction) aby dało się jeździć na
|
||||
// koślawych
|
||||
// sceneriach
|
||||
@@ -3827,18 +3771,7 @@ bool TGround::GetTraction(TDynamicObject *model)
|
||||
else
|
||||
p->hvPowerWire = NULL; // pantograf opuszczony
|
||||
}
|
||||
// if (model->fWahaczeAmp<model->MoverParameters->DistCounter)
|
||||
//{//nieużywana normalnie zmienna ogranicza powtórzone logowania
|
||||
// model->fWahaczeAmp=model->MoverParameters->DistCounter;
|
||||
// ErrorLog(FloatToStrF(1000.0*model->MoverParameters->DistCounter,ffFixed,7,3)+","+FloatToStrF(p->PantTraction,ffFixed,7,3)+","+FloatToStrF(p->fHorizontal,ffFixed,7,3)+","+FloatToStrF(p->PantWys,ffFixed,7,3)+","+AnsiString(p->hvPowerWire?1:0));
|
||||
// //
|
||||
// if (p->fHorizontal>1.0)
|
||||
//{
|
||||
// //Global::iPause|=1; //zapauzowanie symulacji
|
||||
// Global::fTimeSpeed=1; //spowolnienie czasu do obejrzenia pantografu
|
||||
// return true; //łapacz
|
||||
//}
|
||||
//}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
8
Ground.h
8
Ground.h
@@ -285,20 +285,24 @@ class TGround
|
||||
bool InitEvents();
|
||||
#endif
|
||||
bool InitLaunchers();
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
|
||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TGroundNode *Exclude);
|
||||
TTraction * TractionNearestFind(glm::dvec3 &p, int dir, TGroundNode *n);
|
||||
#endif
|
||||
TGroundNode * AddGroundNode(cParser *parser);
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
|
||||
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS
|
||||
void Update_Hidden(); // updates invisible elements of the scene
|
||||
#endif
|
||||
bool GetTraction(TDynamicObject *model);
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
bool AddToQuery( TEvent *Event, TDynamicObject *Node );
|
||||
bool CheckQuery();
|
||||
#endif
|
||||
TGroundNode * DynamicFindAny(std::string const &Name);
|
||||
TGroundNode * DynamicFind(std::string const &Name);
|
||||
#endif
|
||||
void DynamicList(bool all = false);
|
||||
TGroundNode * FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType);
|
||||
TGroundRect * GetRect( double x, double z );
|
||||
@@ -325,7 +329,9 @@ class TGround
|
||||
// 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);
|
||||
#endif
|
||||
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
public:
|
||||
|
||||
12
MemCell.cpp
12
MemCell.cpp
@@ -180,3 +180,15 @@ void TMemCell::AssignEvents(TEvent *e)
|
||||
{ // powiązanie eventu
|
||||
OnSent = e;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// legacy method, initializes traction after deserialization from scenario file
|
||||
void
|
||||
memory_table::InitCells() {
|
||||
|
||||
for( auto *cell : m_items ) {
|
||||
// Ra: eventy komórek pamięci, wykonywane po wysłaniu komendy do zatrzymanego pojazdu
|
||||
cell->AssignEvents( simulation::Events.FindEvent( cell->name() + ":sent" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,8 +61,14 @@ class TMemCell : public editor::basic_node {
|
||||
void AssignEvents(TEvent *e);
|
||||
};
|
||||
|
||||
class memory_manager : public basic_table<TMemCell> {
|
||||
|
||||
|
||||
class memory_table : public basic_table<TMemCell> {
|
||||
|
||||
public:
|
||||
// legacy method, initializes traction after deserialization from scenario file
|
||||
void
|
||||
InitCells();
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -1641,7 +1641,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad model: reference to non-existent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ) );
|
||||
ErrorLog( "Bad model: reference to nonexistent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ) );
|
||||
m_material = null_handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "mczapkie/mctools.h"
|
||||
#include "usefull.h"
|
||||
|
||||
TRealSound::TRealSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic,
|
||||
bool freqmod, double rmin)
|
||||
TRealSound::TRealSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod, double rmin)
|
||||
{
|
||||
Init(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin);
|
||||
}
|
||||
@@ -32,12 +31,7 @@ TRealSound::~TRealSound()
|
||||
// if (this) if (pSound) pSound->Stop();
|
||||
}
|
||||
|
||||
void TRealSound::Free()
|
||||
{
|
||||
}
|
||||
|
||||
void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation, double X, double Y, double Z,
|
||||
bool Dynamic, bool freqmod, double rmin)
|
||||
void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod, double rmin)
|
||||
{
|
||||
// Nazwa=SoundName; //to tak raczej nie zadziała, (SoundName) jest tymczasowe
|
||||
pSound = TSoundsManager::GetFromName(SoundName, Dynamic, &fFrequency);
|
||||
@@ -71,7 +65,7 @@ void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation,
|
||||
dSoundAtt = -1;
|
||||
};
|
||||
|
||||
double TRealSound::ListenerDistance(vector3 ListenerPosition)
|
||||
double TRealSound::ListenerDistance( Math3D::vector3 ListenerPosition)
|
||||
{
|
||||
if (dSoundAtt == -1)
|
||||
{
|
||||
@@ -83,7 +77,7 @@ double TRealSound::ListenerDistance(vector3 ListenerPosition)
|
||||
}
|
||||
}
|
||||
|
||||
void TRealSound::Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition)
|
||||
void TRealSound::Play(double Volume, int Looping, bool ListenerInside, Math3D::vector3 NewPosition)
|
||||
{
|
||||
if (!pSound)
|
||||
return;
|
||||
@@ -155,11 +149,6 @@ void TRealSound::Play(double Volume, int Looping, bool ListenerInside, vector3 N
|
||||
}
|
||||
};
|
||||
|
||||
void TRealSound::Start(){
|
||||
// włączenie dźwięku
|
||||
|
||||
};
|
||||
|
||||
void TRealSound::Stop()
|
||||
{
|
||||
DWORD stat;
|
||||
@@ -231,17 +220,14 @@ void TRealSound::ResetPosition()
|
||||
pSound->SetCurrentPosition(0);
|
||||
}
|
||||
|
||||
TTextSound::TTextSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z,
|
||||
bool Dynamic, bool freqmod, double rmin)
|
||||
: TRealSound(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin)
|
||||
TTextSound::TTextSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod, double rmin) :
|
||||
TRealSound(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin)
|
||||
{
|
||||
Init(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin);
|
||||
}
|
||||
|
||||
void TTextSound::Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z,
|
||||
bool Dynamic, bool freqmod, double rmin)
|
||||
void TTextSound::Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod, double rmin)
|
||||
{ // dodatkowo doczytuje plik tekstowy
|
||||
//TRealSound::Init(SoundName, SoundAttenuation, X, Y, Z, Dynamic, freqmod, rmin);
|
||||
fTime = GetWaveTime();
|
||||
std::string txt(SoundName);
|
||||
txt.erase( txt.rfind( '.' ) ); // obcięcie rozszerzenia
|
||||
@@ -253,15 +239,11 @@ void TTextSound::Init(std::string const &SoundName, double SoundAttenuation, dou
|
||||
txt = "sounds\\" + txt; //ścieżka może nie być podana
|
||||
if (FileExists(txt))
|
||||
{ // wczytanie
|
||||
/* TFileStream *ts = new TFileStream(txt, fmOpenRead);
|
||||
asText = AnsiString::StringOfChar(' ', ts->Size);
|
||||
ts->Read(asText.c_str(), ts->Size);
|
||||
delete ts;
|
||||
*/ std::ifstream inputfile( txt );
|
||||
std::ifstream inputfile( txt );
|
||||
asText.assign( std::istreambuf_iterator<char>( inputfile ), std::istreambuf_iterator<char>() );
|
||||
}
|
||||
};
|
||||
void TTextSound::Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition)
|
||||
void TTextSound::Play(double Volume, int Looping, bool ListenerInside, Math3D::vector3 NewPosition)
|
||||
{
|
||||
if (false == asText.empty())
|
||||
{ // jeśli ma powiązany tekst
|
||||
|
||||
69
RealSound.h
69
RealSound.h
@@ -7,24 +7,25 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef RealSoundH
|
||||
#define RealSoundH
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "Sound.h"
|
||||
#include "Geometry.h"
|
||||
|
||||
class TRealSound
|
||||
{
|
||||
#include "Sound.h"
|
||||
#include "dumb3d.h"
|
||||
#include "names.h"
|
||||
|
||||
class TRealSound {
|
||||
|
||||
protected:
|
||||
PSound pSound = nullptr;
|
||||
// char *Nazwa; // dla celow odwszawiania NOTE: currently not used anywhere
|
||||
double fDistance = 0.0,
|
||||
fPreviousDistance = 0.0; // dla liczenia Dopplera
|
||||
double fDistance = 0.0;
|
||||
double fPreviousDistance = 0.0; // dla liczenia Dopplera
|
||||
float fFrequency = 22050.0; // częstotliwość samplowania pliku
|
||||
int iDoppler = 0; // Ra 2014-07: możliwość wyłączenia efektu Dopplera np. dla śpiewu ptaków
|
||||
public:
|
||||
vector3 vSoundPosition; // polozenie zrodla dzwieku
|
||||
std::string m_name;
|
||||
Math3D::vector3 vSoundPosition; // polozenie zrodla dzwieku
|
||||
double dSoundAtt = -1.0; // odleglosc polowicznego zaniku dzwieku
|
||||
double AM = 0.0; // mnoznik amplitudy
|
||||
double AA = 0.0; // offset amplitudy
|
||||
@@ -32,37 +33,43 @@ class TRealSound
|
||||
double FA = 0.0; // offset czestotliwosci
|
||||
bool bLoopPlay = false; // czy zapętlony dźwięk jest odtwarzany
|
||||
TRealSound() = default;
|
||||
TRealSound( std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic,
|
||||
bool freqmod = false, double rmin = 0.0);
|
||||
TRealSound( std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod = false, double rmin = 0.0 );
|
||||
~TRealSound();
|
||||
void Free();
|
||||
void Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic,
|
||||
bool freqmod = false, double rmin = 0.0);
|
||||
double ListenerDistance(vector3 ListenerPosition);
|
||||
void Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition);
|
||||
void Start();
|
||||
void Init( std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod = false, double rmin = 0.0 );
|
||||
double ListenerDistance( Math3D::vector3 ListenerPosition);
|
||||
void Play(double Volume, int Looping, bool ListenerInside, Math3D::vector3 NewPosition);
|
||||
void Stop();
|
||||
void AdjFreq(double Freq, double dt);
|
||||
void SetPan(int Pan);
|
||||
double GetWaveTime(); // McZapkie TODO: dorobic dla roznych bps
|
||||
int GetStatus();
|
||||
void ResetPosition();
|
||||
// void FreqReset(float f=22050.0) {fFrequency=f;};
|
||||
bool Empty() { return ( pSound == nullptr ); }
|
||||
void
|
||||
name( std::string Name ) {
|
||||
m_name = Name; }
|
||||
std::string const &
|
||||
name() const {
|
||||
return m_name; }
|
||||
glm::dvec3
|
||||
location() const {
|
||||
return vSoundPosition; };
|
||||
};
|
||||
|
||||
class TTextSound : public TRealSound
|
||||
{ // dźwięk ze stenogramem
|
||||
|
||||
|
||||
class TTextSound : public TRealSound {
|
||||
// dźwięk ze stenogramem
|
||||
std::string asText;
|
||||
float fTime; // czas trwania
|
||||
public:
|
||||
TTextSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z,
|
||||
bool Dynamic, bool freqmod = false, double rmin = 0.0);
|
||||
void Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z,
|
||||
bool Dynamic, bool freqmod = false, double rmin = 0.0);
|
||||
void Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition);
|
||||
TTextSound(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod = false, double rmin = 0.0);
|
||||
void Init(std::string const &SoundName, double SoundAttenuation, double X, double Y, double Z, bool Dynamic, bool freqmod = false, double rmin = 0.0);
|
||||
void Play(double Volume, int Looping, bool ListenerInside, Math3D::vector3 NewPosition);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TSynthSound
|
||||
{ // klasa generująca sygnał odjazdu (Rp12, Rp13), potem rozbudować o pracę manewrowego...
|
||||
int iIndex[44]; // indeksy początkowe, gdy mamy kilka wariantów dźwięków składowych
|
||||
@@ -74,10 +81,16 @@ class TSynthSound
|
||||
// 41 - "tysiące"
|
||||
// 42 - indeksy początkowe dla "odjazd"
|
||||
// 43 - indeksy początkowe dla "gotów"
|
||||
PSound *sSound; // posortowana tablica dźwięków, rozmiar zależny od liczby znalezionych plików
|
||||
PSound sSound; // posortowana tablica dźwięków, rozmiar zależny od liczby znalezionych plików
|
||||
// a może zamiast wielu plików/dźwięków zrobić jeden połączony plik i posługiwać się czasem
|
||||
// od..do?
|
||||
};
|
||||
|
||||
|
||||
|
||||
// collection of generators for power grid present in the scene
|
||||
class sound_table : public basic_table<TTextSound> {
|
||||
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
39
Segment.cpp
39
Segment.cpp
@@ -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->NameGet() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||
ErrorLog( "Bad geometry: 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->NameGet() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||
ErrorLog( "Bad geometry: shape estimation failed for spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||
// MessageBox(0,"Too many iterations","GetTFromS",MB_OK);
|
||||
return fTime;
|
||||
};
|
||||
@@ -323,23 +323,28 @@ Math3D::vector3 TSegment::GetPoint(double const fDistance) const
|
||||
}
|
||||
};
|
||||
|
||||
void TSegment::RaPositionGet(double const fDistance, Math3D::vector3 &p, Math3D::vector3 &a) const
|
||||
{ // ustalenie pozycji osi na torze, przechyłki, pochylenia i kierunku jazdy
|
||||
if (bCurve)
|
||||
{ // można by wprowadzić uproszczony wzór dla okręgów płaskich
|
||||
double t = GetTFromS(fDistance); // aproksymacja dystansu na krzywej Beziera na parametr (t)
|
||||
p = RaInterpolate(t);
|
||||
a.x = (1.0 - t) * fRoll1 + (t)*fRoll2; // przechyłka w danym miejscu (zmienia się liniowo)
|
||||
// ustalenie pozycji osi na torze, przechyłki, pochylenia i kierunku jazdy
|
||||
void TSegment::RaPositionGet(double const fDistance, Math3D::vector3 &p, Math3D::vector3 &a) const {
|
||||
|
||||
if (bCurve) {
|
||||
// można by wprowadzić uproszczony wzór dla okręgów płaskich
|
||||
auto const t = GetTFromS(fDistance); // aproksymacja dystansu na krzywej Beziera na parametr (t)
|
||||
p = FastGetPoint( t );
|
||||
// przechyłka w danym miejscu (zmienia się liniowo)
|
||||
a.x = interpolate<double>( fRoll1, fRoll2, t );
|
||||
// pochodna jest 3*A*t^2+2*B*t+C
|
||||
a.y = atan(t * (t * 3.0 * vA.y + vB.y + vB.y) + vC.y); // pochylenie krzywej (w pionie)
|
||||
a.z = -atan2(t * (t * 3.0 * vA.x + vB.x + vB.x) + vC.x,
|
||||
t * (t * 3.0 * vA.z + vB.z + vB.z) + vC.z); // kierunek krzywej w planie
|
||||
auto const tangent = t * ( t * 3.0 * vA + vB + vB ) + vC;
|
||||
// pochylenie krzywej (w pionie)
|
||||
a.y = std::atan( tangent.y );
|
||||
// kierunek krzywej w planie
|
||||
a.z = -std::atan2( tangent.x, tangent.z );
|
||||
}
|
||||
else
|
||||
{ // wyliczenie dla odcinka prostego jest prostsze
|
||||
double t = fDistance / fLength; // zerowych torów nie ma
|
||||
p = ((1.0 - t) * Point1 + (t)*Point2);
|
||||
a.x = (1.0 - t) * fRoll1 + (t)*fRoll2; // przechyłka w danym miejscu (zmienia się liniowo)
|
||||
else {
|
||||
// wyliczenie dla odcinka prostego jest prostsze
|
||||
auto const t = fDistance / fLength; // zerowych torów nie ma
|
||||
p = FastGetPoint( t );
|
||||
// przechyłka w danym miejscu (zmienia się liniowo)
|
||||
a.x = interpolate<double>( fRoll1, fRoll2, t );
|
||||
a.y = fStoop; // pochylenie toru prostego
|
||||
a.z = fDirection; // kierunek toru w planie
|
||||
}
|
||||
|
||||
36
Segment.h
36
Segment.h
@@ -14,37 +14,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Classes.h"
|
||||
#include "usefull.h"
|
||||
|
||||
// 110405 Ra: klasa punktów przekroju z normalnymi
|
||||
/*
|
||||
class vector6 : public Math3D::vector3
|
||||
{ // punkt przekroju wraz z wektorem normalnym
|
||||
public:
|
||||
Math3D::vector3 n;
|
||||
vector6()
|
||||
{
|
||||
x = y = z = n.x = n.z = 0.0;
|
||||
n.y = 1.0;
|
||||
};
|
||||
vector6(double a, double b, double c, double d, double e, double f)
|
||||
{
|
||||
x = a;
|
||||
y = b;
|
||||
z = c;
|
||||
n.x = 0.0;
|
||||
n.y = 1.0;
|
||||
n.z = 0.0;
|
||||
}; // Ra: bo na razie są z tym problemy
|
||||
vector6(double a, double b, double c)
|
||||
{
|
||||
x = a;
|
||||
y = b;
|
||||
z = c;
|
||||
n.x = 0.0;
|
||||
n.y = 1.0;
|
||||
n.z = 0.0;
|
||||
};
|
||||
};
|
||||
*/
|
||||
class TSegment
|
||||
{ // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
|
||||
private:
|
||||
@@ -60,7 +29,6 @@ class TSegment
|
||||
double fStoop = 0.0; // Ra: kąt wzniesienia; dla łuku od Point1
|
||||
Math3D::vector3 vA, vB, vC; // współczynniki wielomianów trzeciego stopnia vD==Point1
|
||||
TTrack *pOwner = nullptr; // wskaźnik na właściciela
|
||||
double fAngle[ 2 ] = { 0.0, 0.0 }; // kąty zakończenia drogi na przejazdach
|
||||
|
||||
Math3D::vector3
|
||||
GetFirstDerivative(double const fTime) const;
|
||||
@@ -140,10 +108,6 @@ public:
|
||||
int
|
||||
RaSegCount() const {
|
||||
return fTsBuffer ? iSegCount : 1; };
|
||||
inline
|
||||
void
|
||||
AngleSet(int const i, double const a) {
|
||||
fAngle[i] = a; };
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
63
Track.cpp
63
Track.cpp
@@ -26,6 +26,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "AnimModel.h"
|
||||
#include "MemCell.h"
|
||||
#include "Event.h"
|
||||
#include "simulation.h"
|
||||
|
||||
// 101206 Ra: trapezoidalne drogi i tory
|
||||
// 110720 Ra: rozprucie zwrotnicy i odcinki izolowane
|
||||
@@ -2651,6 +2652,31 @@ int TTrack::TestPoint(vector3 *Point)
|
||||
return -1;
|
||||
};
|
||||
|
||||
// retrieves list of the track's end points
|
||||
std::vector<glm::dvec3>
|
||||
TTrack::endpoints() const {
|
||||
|
||||
switch( eType ) {
|
||||
case tt_Normal:
|
||||
case tt_Table: {
|
||||
return {
|
||||
glm::dvec3{ Segment->FastGetPoint_0() },
|
||||
glm::dvec3{ Segment->FastGetPoint_1() } };
|
||||
}
|
||||
case tt_Switch:
|
||||
case tt_Cross: {
|
||||
return {
|
||||
glm::dvec3{ SwitchExtension->Segments[ 0 ]->FastGetPoint_0() },
|
||||
glm::dvec3{ SwitchExtension->Segments[ 0 ]->FastGetPoint_1() },
|
||||
glm::dvec3{ SwitchExtension->Segments[ 1 ]->FastGetPoint_0() },
|
||||
glm::dvec3{ SwitchExtension->Segments[ 1 ]->FastGetPoint_1() } };
|
||||
}
|
||||
default: {
|
||||
return{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrack::MovedUp1(float const dh)
|
||||
{ // poprawienie przechyłki wymaga wydłużenia podsypki
|
||||
fTexHeight1 += dh;
|
||||
@@ -2745,11 +2771,11 @@ TTrack * TTrack::Connected(int s, double &d) const
|
||||
// legacy method, initializes tracks after deserialization from scenario file
|
||||
void
|
||||
path_table::InitTracks() {
|
||||
/*
|
||||
TGroundNode *Model;
|
||||
int iConnection;
|
||||
|
||||
for( auto *track : m_paths ) {
|
||||
int connection { -1 };
|
||||
TTrack *matchingtrack { nullptr };
|
||||
|
||||
for( auto *track : m_items ) {
|
||||
|
||||
track->AssignEvents(
|
||||
simulation::Events.FindEvent( track->asEvent0Name ),
|
||||
@@ -2776,30 +2802,32 @@ path_table::InitTracks() {
|
||||
}
|
||||
|
||||
switch (track->eType) {
|
||||
/*
|
||||
// TODO: re-enable
|
||||
case tt_Table: {
|
||||
// obrotnicę też łączymy na starcie z innymi torami
|
||||
// szukamy modelu o tej samej nazwie
|
||||
Model = FindGroundNode(Current->asName, TP_MODEL);
|
||||
auto *instance = simulation::Instances.find( trackname );
|
||||
// wiązanie toru z modelem obrotnicy
|
||||
track->RaAssign(
|
||||
Current,
|
||||
( Model ?
|
||||
Model->Model :
|
||||
nullptr ),
|
||||
instance,
|
||||
simulation::Events.FindEvent( trackname + ":done" ),
|
||||
simulation::Events.FindEvent( trackname + ":joined" ) );
|
||||
if( Model == nullptr ) {
|
||||
if( instance == nullptr ) {
|
||||
// jak nie ma modelu to pewnie jest wykolejnica, a ta jest domyślnie zamknięta i wykoleja
|
||||
break;
|
||||
}
|
||||
// no break on purpose:
|
||||
// jak coś pójdzie źle, to robimy z tego normalny tor
|
||||
}
|
||||
*/
|
||||
case tt_Normal: {
|
||||
// tylko proste są podłączane do rozjazdów, stąd dwa rozjazdy się nie połączą ze sobą
|
||||
if( track->CurrentPrev() == nullptr ) {
|
||||
// tylko jeśli jeszcze nie podłączony
|
||||
auto *matchingtrack = simulation::Region.FindTrack( track->CurrentSegment()->FastGetPoint_0(), iConnection, track );
|
||||
switch( iConnection ) {
|
||||
std::tie( matchingtrack, connection ) = simulation::Region->find_path( track->CurrentSegment()->FastGetPoint_0(), track );
|
||||
switch( connection ) {
|
||||
case -1: // Ra: pierwsza koncepcja zawijania samochodów i statków
|
||||
// if ((Track->iCategoryFlag&1)==0) //jeśli nie jest torem szynowym
|
||||
// Track->ConnectPrevPrev(Track,0); //łączenie końca odcinka do samego siebie
|
||||
@@ -2830,12 +2858,14 @@ path_table::InitTracks() {
|
||||
matchingtrack->SetConnections( 1 ); // robi też Switch(0)
|
||||
matchingtrack->Switch( 0 );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( track->CurrentNext() == nullptr ) {
|
||||
// tylko jeśli jeszcze nie podłączony
|
||||
auto *matchingtrack = simulation::Region.FindTrack( track->CurrentSegment()->FastGetPoint_1(), iConnection, track );
|
||||
switch( iConnection ) {
|
||||
std::tie( matchingtrack, connection ) = simulation::Region->find_path( track->CurrentSegment()->FastGetPoint_1(), track );
|
||||
switch( connection ) {
|
||||
case -1: // Ra: pierwsza koncepcja zawijania samochodów i statków
|
||||
// if ((Track->iCategoryFlag&1)==0) //jeśli nie jest torem szynowym
|
||||
// Track->ConnectNextNext(Track,1); //łączenie końca odcinka do samego siebie
|
||||
@@ -2866,6 +2896,8 @@ path_table::InitTracks() {
|
||||
matchingtrack->SetConnections( 1 ); // robi też Switch(0)
|
||||
// tmp->Switch(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2910,11 +2942,12 @@ path_table::InitTracks() {
|
||||
else {
|
||||
// utworzenie automatycznej komórki
|
||||
// TODO: determine suitable location for this one, create and add world reference node
|
||||
auto *memorycell = new TMemCell( isolated->asName ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
||||
scene::node_data nodedata;
|
||||
nodedata.name = isolated->asName;
|
||||
auto *memorycell = new TMemCell( nodedata ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
||||
simulation::Memory.insert( memorycell );
|
||||
isolated->pMemCell = memorycell; // wskaźnik komóki przekazany do odcinka izolowanego
|
||||
}
|
||||
isolated = isolated->Next();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
4
Track.h
4
Track.h
@@ -119,7 +119,6 @@ class TTrack : public editor::basic_node {
|
||||
friend class opengl_renderer;
|
||||
|
||||
private:
|
||||
// TGroundNode * pMyNode = nullptr; // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
|
||||
TIsolated * pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
|
||||
std::shared_ptr<TSwitchExtension> SwitchExtension; // dodatkowe dane do toru, który jest zwrotnicą
|
||||
std::shared_ptr<TSegment> Segment;
|
||||
@@ -234,6 +233,9 @@ public:
|
||||
void
|
||||
origin( glm::dvec3 Origin ) {
|
||||
m_origin = Origin; }
|
||||
// retrieves list of the track's end points
|
||||
std::vector<glm::dvec3>
|
||||
endpoints() const;
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
void create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ); // wypełnianie VBO
|
||||
|
||||
314
Traction.cpp
314
Traction.cpp
@@ -91,7 +91,6 @@ sekcji z sąsiedniego przęsła).
|
||||
*/
|
||||
|
||||
TTraction::TTraction( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||
|
||||
// legacy constructor
|
||||
TTraction::TTraction( std::string Name ) {
|
||||
|
||||
@@ -173,6 +172,13 @@ TTraction::Load( cParser *parser, glm::dvec3 const &pOrigin ) {
|
||||
m_location = interpolate( pPoint2, pPoint1, 0.5 );
|
||||
}
|
||||
|
||||
// retrieves list of the track's end points
|
||||
std::vector<glm::dvec3>
|
||||
TTraction::endpoints() const {
|
||||
|
||||
return { pPoint1, pPoint2 };
|
||||
}
|
||||
|
||||
std::size_t
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ) {
|
||||
@@ -621,205 +627,213 @@ TTraction::wire_color() const {
|
||||
// legacy method, initializes traction after deserialization from scenario file
|
||||
void
|
||||
traction_table::InitTraction() {
|
||||
/*
|
||||
|
||||
//łączenie drutów ze sobą oraz z torami i eventami
|
||||
// TGroundNode *nCurrent, *nTemp;
|
||||
// TTraction *tmp; // znalezione przęsło
|
||||
int iConnection;
|
||||
std::string name;
|
||||
|
||||
int connection { -1 };
|
||||
TTraction *matchingtraction { nullptr };
|
||||
|
||||
for( auto *traction : m_items ) {
|
||||
// podłączenie do zasilacza, żeby można było sumować prąd kilku pojazdów
|
||||
// a jednocześnie z jednego miejsca zmieniać napięcie eventem
|
||||
// wykonywane najpierw, żeby można było logować podłączenie 2 zasilaczy do jednego drutu
|
||||
// izolator zawieszony na przęśle jest ma być osobnym odcinkiem drutu o długości ok. 1m,
|
||||
// podłączonym do zasilacza o nazwie "*" (gwiazka); "none" nie będzie odpowiednie
|
||||
nTemp = FindGroundNode(traction->asPowerSupplyName, TP_TRACTIONPOWERSOURCE);
|
||||
if (nTemp) // jak zasilacz znaleziony
|
||||
traction->PowerSet(nTemp->psTractionPowerSource); // to podłączyć do przęsła
|
||||
else if (traction->asPowerSupplyName != "*") // gwiazdka dla przęsła z izolatorem
|
||||
if (traction->asPowerSupplyName != "none") // dopuszczamy na razie brak podłączenia?
|
||||
{ // logowanie błędu i utworzenie zasilacza o domyślnej zawartości
|
||||
ErrorLog("Missed TractionPowerSource: " + traction->asPowerSupplyName);
|
||||
nTemp = new TGroundNode();
|
||||
nTemp->iType = TP_TRACTIONPOWERSOURCE;
|
||||
nTemp->asName = traction->asPowerSupplyName;
|
||||
nTemp->psTractionPowerSource = new TTractionPowerSource(nTemp);
|
||||
nTemp->psTractionPowerSource->Init(traction->NominalVoltage, traction->MaxCurrent);
|
||||
nTemp->nNext = nRootOfType[nTemp->iType]; // ostatni dodany dołączamy na końcu
|
||||
// nowego
|
||||
nRootOfType[nTemp->iType] = nTemp; // ustawienie nowego na początku listy
|
||||
auto *powersource = simulation::Powergrid.find( traction->asPowerSupplyName );
|
||||
if( powersource ) {
|
||||
// jak zasilacz znaleziony to podłączyć do przęsła
|
||||
traction->PowerSet( powersource );
|
||||
}
|
||||
else {
|
||||
if( ( traction->asPowerSupplyName != "*" ) // gwiazdka dla przęsła z izolatorem
|
||||
&& ( traction->asPowerSupplyName != "none" ) ) { // dopuszczamy na razie brak podłączenia?
|
||||
// logowanie błędu i utworzenie zasilacza o domyślnej zawartości
|
||||
ErrorLog( "Bad scenario: traction piece connected to nonexistent power source \"" + traction->asPowerSupplyName + "\"" );
|
||||
scene::node_data nodedata;
|
||||
nodedata.name = traction->asPowerSupplyName;
|
||||
powersource = new TTractionPowerSource( nodedata );
|
||||
powersource->Init( traction->NominalVoltage, traction->MaxCurrent );
|
||||
simulation::Powergrid.insert( powersource );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto *traction : m_items ) {
|
||||
|
||||
if (!traction->hvNext[0]) // tylko jeśli jeszcze nie podłączony
|
||||
{
|
||||
tmp = FindTraction(traction->pPoint1, iConnection, nCurrent);
|
||||
switch (iConnection)
|
||||
{
|
||||
case 0:
|
||||
traction->Connect(0, tmp, 0);
|
||||
break;
|
||||
case 1:
|
||||
traction->Connect(0, tmp, 1);
|
||||
if (!traction->hvNext[0]) {
|
||||
// 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;
|
||||
}
|
||||
if (traction->hvNext[0]) // jeśli został podłączony
|
||||
if (traction->psSection && tmp->psSection) // tylko przęsło z izolatorem może nie
|
||||
// mieć zasilania, bo ma 2, trzeba
|
||||
// sprawdzać sąsiednie
|
||||
if (traction->psSection !=
|
||||
tmp->psSection) // połączone odcinki mają różne zasilacze
|
||||
{ // to może być albo podłączenie podstacji lub kabiny sekcyjnej do sekcji, albo
|
||||
// błąd
|
||||
if (traction->psSection->bSection && !tmp->psSection->bSection)
|
||||
{ //(tmp->psSection) jest podstacją, a (Traction->psSection) nazwą sekcji
|
||||
tmp->PowerSet(traction->psSection); // zastąpienie wskazaniem sekcji
|
||||
}
|
||||
else if (!traction->psSection->bSection && tmp->psSection->bSection)
|
||||
{ //(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
|
||||
traction->PowerSet(tmp->psSection); // zastąpienie wskazaniem sekcji
|
||||
}
|
||||
else // jeśli obie to sekcje albo obie podstacje, to będzie błąd
|
||||
ErrorLog("Bad power: at " +
|
||||
to_string(traction->pPoint1.x, 2, 6) + " " +
|
||||
to_string(traction->pPoint1.y, 2, 6) + " " +
|
||||
to_string(traction->pPoint1.z, 2, 6));
|
||||
}
|
||||
}
|
||||
if (!traction->hvNext[1]) // tylko jeśli jeszcze nie podłączony
|
||||
{
|
||||
tmp = FindTraction(traction->pPoint2, iConnection, nCurrent);
|
||||
switch (iConnection)
|
||||
{
|
||||
case 0:
|
||||
traction->Connect(1, tmp, 0);
|
||||
break;
|
||||
case 1:
|
||||
traction->Connect(1, tmp, 1);
|
||||
case 1: {
|
||||
traction->Connect( 0, matchingtraction, 1 );
|
||||
break;
|
||||
}
|
||||
if (traction->hvNext[1]) // jeśli został podłączony
|
||||
if (traction->psSection && tmp->psSection) // tylko przęsło z izolatorem może nie
|
||||
// mieć zasilania, bo ma 2, trzeba
|
||||
// sprawdzać sąsiednie
|
||||
if (traction->psSection != tmp->psSection)
|
||||
{ // to może być albo podłączenie podstacji lub kabiny sekcyjnej do sekcji, albo
|
||||
// błąd
|
||||
if (traction->psSection->bSection && !tmp->psSection->bSection)
|
||||
{ //(tmp->psSection) jest podstacją, a (Traction->psSection) nazwą sekcji
|
||||
tmp->PowerSet(traction->psSection); // zastąpienie wskazaniem sekcji
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( traction->hvNext[ 0 ] ) {
|
||||
// jeśli został podłączony
|
||||
if( ( traction->psSection != nullptr )
|
||||
&& ( matchingtraction->psSection != nullptr ) ) {
|
||||
// tylko przęsło z izolatorem może nie mieć zasilania, bo ma 2, trzeba sprawdzać sąsiednie
|
||||
if( traction->psSection != matchingtraction->psSection ) {
|
||||
// połączone odcinki mają różne zasilacze
|
||||
// to może być albo podłączenie podstacji lub kabiny sekcyjnej do sekcji, albo błąd
|
||||
if( ( true == traction->psSection->bSection )
|
||||
&& ( false == matchingtraction->psSection->bSection ) ) {
|
||||
//(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 ) ) {
|
||||
//(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
|
||||
traction->PowerSet( matchingtraction->psSection ); // zastąpienie wskazaniem sekcji
|
||||
}
|
||||
else {
|
||||
// jeśli obie to sekcje albo obie podstacje, to będzie błąd
|
||||
ErrorLog( "Bad scenario: faulty traction power connection at location " + to_string( traction->pPoint1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!traction->hvNext[1]) {
|
||||
// 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 1: {
|
||||
traction->Connect( 1, matchingtraction, 1 );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( traction->hvNext[ 1 ] ) {
|
||||
// jeśli został podłączony
|
||||
if( ( traction->psSection != nullptr )
|
||||
&& ( matchingtraction->psSection != nullptr ) ) {
|
||||
// tylko przęsło z izolatorem może nie mieć zasilania, bo ma 2, trzeba sprawdzać sąsiednie
|
||||
if( traction->psSection != matchingtraction->psSection ) {
|
||||
// to może być albo podłączenie podstacji lub kabiny sekcyjnej do sekcji, albo błąd
|
||||
if( ( true == traction->psSection->bSection )
|
||||
&& ( false == matchingtraction->psSection->bSection ) ) {
|
||||
//(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 ) ) {
|
||||
//(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
|
||||
traction->PowerSet( matchingtraction->psSection ); // zastąpienie wskazaniem sekcji
|
||||
}
|
||||
else {
|
||||
// jeśli obie to sekcje albo obie podstacje, to będzie błąd
|
||||
ErrorLog( "Bad scenario: faulty traction power connection at location " + to_string( traction->pPoint2 ) );
|
||||
}
|
||||
}
|
||||
else if (!traction->psSection->bSection && tmp->psSection->bSection)
|
||||
{ //(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
|
||||
traction->PowerSet(tmp->psSection); // zastąpienie wskazaniem sekcji
|
||||
}
|
||||
else // jeśli obie to sekcje albo obie podstacje, to będzie błąd
|
||||
ErrorLog("Bad power: at " +
|
||||
to_string(traction->pPoint2.x, 2, 6) + " " +
|
||||
to_string(traction->pPoint2.y, 2, 6) + " " +
|
||||
to_string(traction->pPoint2.z, 2, 6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iConnection = 0; // teraz będzie licznikiem końców
|
||||
auto endcount { 0 };
|
||||
for( auto *traction : m_items ) {
|
||||
// operacje mające na celu wykrywanie bieżni wspólnych i łączenie przęseł naprążania
|
||||
if (traction->WhereIs()) // oznakowanie przedostatnich przęseł
|
||||
{ // poszukiwanie bieżni wspólnej dla przedostatnich przęseł, również w celu połączenia
|
||||
// zasilania
|
||||
// to się nie sprawdza, bo połączyć się mogą dwa niezasilane odcinki jako najbliższe
|
||||
// sobie
|
||||
// nCurrent->hvTraction->hvParallel=TractionNearestFind(nCurrent->pCenter,0,nCurrent);
|
||||
// //szukanie najbliższego przęsła
|
||||
// trzeba by zliczać końce, a potem wpisać je do tablicy, aby sukcesywnie podłączać do
|
||||
// zasilaczy
|
||||
if( traction->WhereIs() ) {
|
||||
// true for outer pieces of the traction section
|
||||
traction->iTries = 5; // oznaczanie końcowych
|
||||
++iConnection;
|
||||
++endcount;
|
||||
}
|
||||
if (traction->fResistance[0] == 0.0)
|
||||
{
|
||||
traction->ResistanceCalc(); // obliczanie przęseł w segmencie z bezpośrednim zasilaniem
|
||||
// ErrorLog("Section "+nCurrent->hvTraction->asPowerSupplyName+" connected"); //jako
|
||||
// niby błąd będzie bardziej widoczne
|
||||
if (traction->fResistance[0] == 0.0) {
|
||||
// obliczanie przęseł w segmencie z bezpośrednim zasilaniem
|
||||
traction->ResistanceCalc();
|
||||
traction->iTries = 0; // nie potrzeba mu szukać zasilania
|
||||
}
|
||||
// if (!Traction->hvParallel) //jeszcze utworzyć pętle z bieżni wspólnych
|
||||
}
|
||||
int zg = 0; // zgodność kierunku przęseł, tymczasowo iterator do tabeli końców
|
||||
// końców jest ok. 10 razy mniej niż wszystkich przęseł (Quark: 216)
|
||||
TGroundNode **nEnds = new TGroundNode *[iConnection];
|
||||
|
||||
std::vector<TTraction *> ends; ends.reserve( endcount );
|
||||
for( auto *traction : m_items ) {
|
||||
//łączenie bieżni wspólnych, w tym oznaczanie niepodanych jawnie
|
||||
if (!traction->asParallel.empty()) // będzie wskaźnik na inne przęsło
|
||||
if( false == traction->asParallel.empty() ) {
|
||||
// będzie wskaźnik na inne przęsło
|
||||
if( ( traction->asParallel == "none" )
|
||||
|| ( traction->asParallel == "*" ) ) {
|
||||
// jeśli nieokreślone
|
||||
traction->iLast = 2; // jakby przedostatni - niech po prostu szuka (iLast już przeliczone)
|
||||
}
|
||||
else if (!traction->hvParallel) // jeśli jeszcze nie został włączony w kółko
|
||||
{
|
||||
else if( traction->hvParallel == nullptr ) {
|
||||
// jeśli jeszcze nie został włączony w kółko
|
||||
auto *nTemp = find( traction->asParallel );
|
||||
if (nTemp)
|
||||
{ // o ile zostanie znalezione przęsło o takiej nazwie
|
||||
if (!nTemp->hvParallel) // jeśli tamten jeszcze nie ma wskaźnika bieżni wspólnej
|
||||
if( nTemp != nullptr ) {
|
||||
// o ile zostanie znalezione przęsło o takiej nazwie
|
||||
if( nTemp->hvParallel == nullptr ) {
|
||||
// jeśli tamten jeszcze nie ma wskaźnika bieżni wspólnej
|
||||
traction->hvParallel = nTemp; // wpisać siebie i dalej dać mu wskaźnik zwrotny
|
||||
else // a jak ma, to albo dołączyć się do kółeczka
|
||||
}
|
||||
else {
|
||||
// a jak ma, to albo dołączyć się do kółeczka
|
||||
traction->hvParallel = nTemp->hvParallel; // przjąć dotychczasowy wskaźnik od niego
|
||||
}
|
||||
nTemp->hvParallel = traction; // i na koniec ustawienie wskaźnika zwrotnego
|
||||
}
|
||||
if (!traction->hvParallel)
|
||||
if( traction->hvParallel == nullptr ) {
|
||||
ErrorLog( "Missed overhead: " + traction->asParallel ); // logowanie braku
|
||||
}
|
||||
if (traction->iTries > 0) // 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ń
|
||||
}
|
||||
while( zg < iConnection ) {
|
||||
// zapełnienie do końca tablicy, jeśli by jakieś końce wypadły
|
||||
nEnds[ zg++ ] = nullptr;
|
||||
}
|
||||
zg = 1; // nieefektywny przebieg kończy łączenie
|
||||
while (zg)
|
||||
{ // ustalenie zastępczej rezystancji dla każdego przęsła
|
||||
zg = 0; // flaga podłączonych przęseł końcowych: -1=puste wskaźniki, 0=coś zostało,
|
||||
// 1=wykonano łączenie
|
||||
for (int i = 0; i < iConnection; ++i)
|
||||
if (nEnds[i]) // załatwione będziemy zerować
|
||||
{ // każdy przebieg to próba podłączenia końca segmentu naprężania do innego zasilanego
|
||||
// przęsła
|
||||
if (nEnds[i]->hvTraction->hvNext[0])
|
||||
{ // jeśli końcowy ma ciąg dalszy od strony 0 (Point1), szukamy odcinka najbliższego
|
||||
// do Point2
|
||||
if (TractionNearestFind(nEnds[i]->hvTraction->pPoint2, 0,
|
||||
nEnds[i])) // poszukiwanie przęsła
|
||||
{
|
||||
nEnds[i] = NULL;
|
||||
zg = 1; // jak coś zostało podłączone, to może zasilanie gdzieś dodatkowo
|
||||
// dotrze
|
||||
}
|
||||
}
|
||||
else if (nEnds[i]->hvTraction->hvNext[1])
|
||||
{ // jeśli końcowy ma ciąg dalszy od strony 1 (Point2), szukamy odcinka najbliższego
|
||||
// do Point1
|
||||
if (TractionNearestFind(nEnds[i]->hvTraction->pPoint1, 1,
|
||||
nEnds[i])) // poszukiwanie przęsła
|
||||
{
|
||||
nEnds[i] = NULL;
|
||||
zg = 1; // jak coś zostało podłączone, to może zasilanie gdzieś dodatkowo
|
||||
// dotrze
|
||||
if( traction->iTries > 0 ) {
|
||||
// jeśli zaznaczony do podłączenia
|
||||
// wypełnianie tabeli końców w celu szukania im połączeń
|
||||
ends.emplace_back( traction );
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // gdy koniec jest samotny, to na razie nie zostanie podłączony (nie powinno
|
||||
// takich być)
|
||||
nEnds[i] = NULL;
|
||||
|
||||
bool connected; // nieefektywny przebieg kończy łączenie
|
||||
do {
|
||||
// ustalenie zastępczej rezystancji dla każdego przęsła
|
||||
// flaga podłączonych przęseł końcowych: -1=puste wskaźniki, 0=coś zostało, 1=wykonano łączenie
|
||||
connected = false;
|
||||
for( auto &end : ends ) {
|
||||
// załatwione będziemy zerować
|
||||
if( end == nullptr ) { continue; }
|
||||
// każdy przebieg to próba podłączenia końca segmentu naprężania do innego zasilanego przęsła
|
||||
if( end->hvNext[ 0 ] != nullptr ) {
|
||||
// jeśli końcowy ma ciąg dalszy od strony 0 (Point1), szukamy odcinka najbliższego do Point2
|
||||
std::tie( matchingtraction, connection ) = simulation::Region->find_traction( end->pPoint2, end, 0 );
|
||||
if( matchingtraction != nullptr ) {
|
||||
// jak znalezione przęsło z zasilaniem, to podłączenie "równoległe"
|
||||
end->ResistanceCalc( 0, matchingtraction->fResistance[ connection ], matchingtraction->psPower[ connection ] );
|
||||
// jak coś zostało podłączone, to może zasilanie gdzieś dodatkowo dotrze
|
||||
connected = true;
|
||||
end = nullptr;
|
||||
}
|
||||
}
|
||||
else if( end->hvNext[ 1 ] != nullptr ) {
|
||||
// jeśli końcowy ma ciąg dalszy od strony 1 (Point2), szukamy odcinka najbliższego do Point1
|
||||
std::tie( matchingtraction, connection ) = simulation::Region->find_traction( end->pPoint1, end, 1 );
|
||||
if( matchingtraction != nullptr ) {
|
||||
// jak znalezione przęsło z zasilaniem, to podłączenie "równoległe"
|
||||
end->ResistanceCalc( 1, matchingtraction->fResistance[ connection ], matchingtraction->psPower[ connection ] );
|
||||
// jak coś zostało podłączone, to może zasilanie gdzieś dodatkowo dotrze
|
||||
connected = true;
|
||||
end = nullptr;
|
||||
}
|
||||
delete[] nEnds; // nie potrzebne już
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// gdy koniec jest samotny, to na razie nie zostanie podłączony (nie powinno takich być)
|
||||
end = nullptr;
|
||||
}
|
||||
}
|
||||
} while( true == connected );
|
||||
}
|
||||
|
||||
@@ -55,13 +55,16 @@ class TTraction : public editor::basic_node {
|
||||
TTraction( scene::node_data const &Nodedata );
|
||||
// legacy constructor
|
||||
TTraction( std::string Name );
|
||||
virtual ~TTraction() = default;
|
||||
|
||||
void Load( cParser *parser, glm::dvec3 const &pOrigin );
|
||||
// set origin point
|
||||
void
|
||||
origin( glm::dvec3 Origin ) {
|
||||
m_origin = Origin; }
|
||||
// retrieves list of the track's end points
|
||||
std::vector<glm::dvec3>
|
||||
endpoints() const;
|
||||
|
||||
// creates geometry data in specified geometry bank. returns: number of created elements, or NULL
|
||||
// NOTE: deleting nodes doesn't currently release geometry data owned by the node. TODO: implement erasing individual geometry chunks and banks
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
|
||||
@@ -20,14 +20,12 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
TTractionPowerSource::TTractionPowerSource(TGroundNode const *node) :
|
||||
gMyNode( node )
|
||||
{
|
||||
psNode[0] = nullptr; // sekcje zostaną podłączone do zasilaczy
|
||||
psNode[1] = nullptr;
|
||||
};
|
||||
TTractionPowerSource::TTractionPowerSource( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||
// legacy constructor
|
||||
TTractionPowerSource::TTractionPowerSource( std::string Name ) {
|
||||
|
||||
TTractionPowerSource::~TTractionPowerSource(){};
|
||||
m_name = Name;
|
||||
}
|
||||
|
||||
void TTractionPowerSource::Init(double const u, double const i)
|
||||
{ // ustawianie zasilacza przy braku w scenerii
|
||||
@@ -36,61 +34,67 @@ void TTractionPowerSource::Init(double const u, double const i)
|
||||
MaxOutputCurrent = i;
|
||||
};
|
||||
|
||||
bool TTractionPowerSource::Load(cParser *parser)
|
||||
{
|
||||
std::string token;
|
||||
// AnsiString str;
|
||||
// str= Parser->GetNextSymbol()LowerCase();
|
||||
// asName= str;
|
||||
parser->getTokens(5);
|
||||
*parser >> NominalVoltage >> VoltageFrequency >> InternalRes >> MaxOutputCurrent >>
|
||||
FastFuseTimeOut;
|
||||
parser->getTokens();
|
||||
*parser >> FastFuseRepetition;
|
||||
parser->getTokens();
|
||||
*parser >> SlowFuseTimeOut;
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
if (token.compare("recuperation") == 0)
|
||||
Recuperation = true;
|
||||
else if (token.compare("section") == 0) // odłącznik sekcyjny
|
||||
bSection = true; // nie jest źródłem zasilania, a jedynie informuje o prądzie odłączenia
|
||||
// sekcji z obwodu
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
if (token.compare("end") != 0)
|
||||
Error("tractionpowersource end statement missing");
|
||||
// if (!bSection) //odłącznik sekcji zasadniczo nie ma impedancji (0.01 jest OK)
|
||||
if (InternalRes < 0.1) // coś mała ta rezystancja była...
|
||||
InternalRes = 0.2; // tak około 0.2, wg
|
||||
// http://www.ikolej.pl/fileadmin/user_upload/Seminaria_IK/13_05_07_Prezentacja_Kruczek.pdf
|
||||
return true;
|
||||
};
|
||||
bool TTractionPowerSource::Load(cParser *parser) {
|
||||
|
||||
bool TTractionPowerSource::Render()
|
||||
{
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
parser->getTokens( 7, false );
|
||||
*parser
|
||||
#else
|
||||
parser->getTokens( 10, false );
|
||||
*parser
|
||||
>> m_location.x
|
||||
>> m_location.y
|
||||
>> m_location.z
|
||||
#endif
|
||||
>> NominalVoltage
|
||||
>> VoltageFrequency
|
||||
>> InternalRes
|
||||
>> MaxOutputCurrent
|
||||
>> FastFuseTimeOut
|
||||
>> FastFuseRepetition
|
||||
>> SlowFuseTimeOut;
|
||||
|
||||
std::string token { parser->getToken<std::string>() };
|
||||
if( token == "recuperation" ) {
|
||||
Recuperation = true;
|
||||
}
|
||||
else if( token == "section" ) {
|
||||
// odłącznik sekcyjny
|
||||
// nie jest źródłem zasilania, a jedynie informuje o prądzie odłączenia sekcji z obwodu
|
||||
bSection = true;
|
||||
}
|
||||
// skip rest of the section
|
||||
while( ( false == token.empty() )
|
||||
&& ( token != "end" ) ) {
|
||||
|
||||
token = parser->getToken<std::string>();
|
||||
}
|
||||
|
||||
if( InternalRes < 0.1 ) {
|
||||
// coś mała ta rezystancja była...
|
||||
// tak około 0.2, wg
|
||||
// http://www.ikolej.pl/fileadmin/user_upload/Seminaria_IK/13_05_07_Prezentacja_Kruczek.pdf
|
||||
InternalRes = 0.2;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
bool TTractionPowerSource::Update(double dt)
|
||||
{ // powinno być wykonane raz na krok fizyki
|
||||
// if (NominalVoltage * TotalPreviousAdmitance >
|
||||
// MaxOutputCurrent * 0.00000005) // iloczyn napięcia i admitancji daje prąd
|
||||
// ErrorLog("Power overload: \"" + gMyNode->asName + "\" with current " + AnsiString(NominalVoltage * TotalPreviousAdmitance) + "A");
|
||||
if (NominalVoltage * TotalPreviousAdmitance >
|
||||
MaxOutputCurrent) // iloczyn napięcia i admitancji daje prąd
|
||||
{
|
||||
// iloczyn napięcia i admitancji daje prąd
|
||||
if (NominalVoltage * TotalPreviousAdmitance > MaxOutputCurrent) {
|
||||
|
||||
FastFuse = true;
|
||||
FuseCounter += 1;
|
||||
if (FuseCounter > FastFuseRepetition)
|
||||
{
|
||||
if (FuseCounter > FastFuseRepetition) {
|
||||
|
||||
SlowFuse = true;
|
||||
ErrorLog("Power overload: \"" + gMyNode->asName + "\" disabled for " +
|
||||
std::to_string(SlowFuseTimeOut) + "s");
|
||||
ErrorLog( "Power overload: \"" + m_name + "\" disabled for " + std::to_string( SlowFuseTimeOut ) + "s" );
|
||||
}
|
||||
else
|
||||
ErrorLog("Power overload: \"" + gMyNode->asName + "\" disabled for " +
|
||||
std::to_string(FastFuseTimeOut) + "s");
|
||||
else {
|
||||
ErrorLog( "Power overload: \"" + m_name + "\" disabled for " + std::to_string( FastFuseTimeOut ) + "s" );
|
||||
}
|
||||
|
||||
FuseTimer = 0;
|
||||
}
|
||||
if (FastFuse || SlowFuse)
|
||||
@@ -145,4 +149,15 @@ void TTractionPowerSource::PowerSet(TTractionPowerSource *ps)
|
||||
// else ErrorLog("nie może być więcej punktów zasilania niż dwa");
|
||||
};
|
||||
|
||||
|
||||
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
powergridsource_table::update( double const Deltatime ) {
|
||||
|
||||
for( auto *powersource : m_items ) {
|
||||
powersource->Update( Deltatime );
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -7,14 +7,14 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef TractionPowerH
|
||||
#define TractionPowerH
|
||||
#pragma once
|
||||
|
||||
#include "scenenode.h"
|
||||
#include "parser.h" //Tolaris-010603
|
||||
#include "names.h"
|
||||
|
||||
class TGroundNode;
|
||||
class TTractionPowerSource : public editor::basic_node {
|
||||
|
||||
class TTractionPowerSource
|
||||
{
|
||||
private:
|
||||
double NominalVoltage = 0.0;
|
||||
double VoltageFrequency = 0.0;
|
||||
@@ -33,27 +33,34 @@ class TTractionPowerSource
|
||||
bool SlowFuse = false;
|
||||
double FuseTimer = 0.0;
|
||||
int FuseCounter = 0;
|
||||
TGroundNode const *gMyNode = nullptr; // wskaźnik na węzeł rodzica
|
||||
|
||||
protected:
|
||||
public: // zmienne publiczne
|
||||
TTractionPowerSource *psNode[2]; // zasilanie na końcach dla sekcji
|
||||
bool bSection = false; // czy jest sekcją
|
||||
public:
|
||||
// AnsiString asName;
|
||||
TTractionPowerSource(TGroundNode const *node);
|
||||
~TTractionPowerSource();
|
||||
// zmienne publiczne
|
||||
TTractionPowerSource *psNode[ 2 ] = { nullptr, nullptr }; // zasilanie na końcach dla sekcji
|
||||
bool bSection = false; // czy jest sekcją
|
||||
|
||||
TTractionPowerSource( scene::node_data const &Nodedata );
|
||||
// legacy constructor
|
||||
TTractionPowerSource( std::string Name );
|
||||
|
||||
void Init(double const u, double const i);
|
||||
bool Load(cParser *parser);
|
||||
bool Render();
|
||||
bool Update(double dt);
|
||||
double CurrentGet(double res);
|
||||
void VoltageSet(double const v)
|
||||
{
|
||||
NominalVoltage = v;
|
||||
};
|
||||
void VoltageSet(double const v) {
|
||||
NominalVoltage = v; };
|
||||
void PowerSet(TTractionPowerSource *ps);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// collection of generators for power grid present in the scene
|
||||
class powergridsource_table : public basic_table<TTractionPowerSource> {
|
||||
|
||||
public:
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
update( double const Deltatime );
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
12
Train.cpp
12
Train.cpp
@@ -357,14 +357,6 @@ TTrain::TTrain() {
|
||||
fPress[ i ][ j ] = 0.0;
|
||||
}
|
||||
|
||||
TTrain::~TTrain()
|
||||
{
|
||||
if (DynamicObject)
|
||||
if (DynamicObject->Mechanik)
|
||||
DynamicObject->Mechanik->TakeControl(
|
||||
true); // likwidacja kabiny wymaga przejęcia przez AI
|
||||
}
|
||||
|
||||
bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
||||
{ // powiązanie ręcznego sterowania kabiną z pojazdem
|
||||
// Global::pUserDynamic=NewDynamicObject; //pojazd renderowany bez trzęsienia
|
||||
@@ -3587,7 +3579,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
iDoorNo[i] = p->iAnimType[ANIM_DOORS];
|
||||
iUnits[i] = iUnitNo;
|
||||
cCode[i] = p->MoverParameters->TypeName[p->MoverParameters->TypeName.length()];
|
||||
asCarName[i] = p->GetName();
|
||||
asCarName[i] = p->name();
|
||||
bPants[iUnitNo - 1][0] = (bPants[iUnitNo - 1][0] || p->MoverParameters->PantFrontUp);
|
||||
bPants[iUnitNo - 1][1] = (bPants[iUnitNo - 1][1] || p->MoverParameters->PantRearUp);
|
||||
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow);
|
||||
@@ -6259,7 +6251,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
||||
}
|
||||
else if (token == "pyscreen:")
|
||||
{
|
||||
pyScreens.init(*parser, DynamicObject->mdKabina, DynamicObject->GetName(),
|
||||
pyScreens.init(*parser, DynamicObject->mdKabina, DynamicObject->name(),
|
||||
NewCabNo);
|
||||
}
|
||||
// btLampkaUnknown.Init("unknown",mdKabina,false);
|
||||
|
||||
1
Train.h
1
Train.h
@@ -80,7 +80,6 @@ class TTrain
|
||||
bool ShowNextCurrent; // pokaz przd w podlaczonej lokomotywie (ET41)
|
||||
bool InitializeCab(int NewCabNo, std::string const &asFileName);
|
||||
TTrain();
|
||||
~TTrain();
|
||||
// McZapkie-010302
|
||||
bool Init(TDynamicObject *NewDynamicObject, bool e3d = false);
|
||||
void OnKeyDown(int cKey);
|
||||
|
||||
149
World.cpp
149
World.cpp
@@ -207,6 +207,13 @@ void TWorld::TrainDelete(TDynamicObject *d)
|
||||
if (Train)
|
||||
if (Train->Dynamic() != d)
|
||||
return; // nie tego usuwać
|
||||
#ifdef EU07_SCENERY_EDITOR
|
||||
if( ( Train->DynamicObject )
|
||||
&& ( Train->DynamicObject->Mechanik ) ) {
|
||||
// likwidacja kabiny wymaga przejęcia przez AI
|
||||
Train->DynamicObject->Mechanik->TakeControl( true );
|
||||
}
|
||||
#endif
|
||||
delete Train; // i nie ma czym sterować
|
||||
Train = NULL;
|
||||
Controlled = NULL; // tego też już nie ma
|
||||
@@ -263,13 +270,25 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
UILayer.set_progress( "Preparing train / Przygotowanie kabiny" );
|
||||
WriteLog( "Player train init: " + Global::asHumanCtrlVehicle );
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TGroundNode *nPlayerTrain = NULL;
|
||||
#else
|
||||
TDynamicObject *nPlayerTrain;
|
||||
#endif
|
||||
if( Global::asHumanCtrlVehicle != "ghostview" )
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
nPlayerTrain = Ground.DynamicFind( Global::asHumanCtrlVehicle ); // szukanie w tych z obsadą
|
||||
#else
|
||||
nPlayerTrain = simulation::Vehicles.find( Global::asHumanCtrlVehicle );
|
||||
#endif
|
||||
if (nPlayerTrain)
|
||||
{
|
||||
Train = new TTrain();
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
if (Train->Init(nPlayerTrain->DynamicObject))
|
||||
#else
|
||||
if( Train->Init( nPlayerTrain ) )
|
||||
#endif
|
||||
{
|
||||
Controlled = Train->Dynamic();
|
||||
mvControlled = Controlled->ControlledFind()->MoverParameters;
|
||||
@@ -522,7 +541,11 @@ void TWorld::OnKeyDown(int cKey)
|
||||
break;
|
||||
}
|
||||
|
||||
#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 ) );
|
||||
#endif
|
||||
if( ( tmp != nullptr )
|
||||
&& ( tmp != Controlled ) ) {
|
||||
|
||||
@@ -700,7 +723,11 @@ void TWorld::OnKeyDown(int cKey)
|
||||
*/
|
||||
if (cKey == Global::Keys[k_Heating]) // Ra: klawisz nie jest najszczęśliwszy
|
||||
{ // zmiana próżny/ładowny; Ra: zabrane z kabiny
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *temp = Global::DynamicNearest();
|
||||
#else
|
||||
TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false ) );
|
||||
#endif
|
||||
if (temp)
|
||||
{
|
||||
if (Global::shiftState ? temp->MoverParameters->IncBrakeMult() :
|
||||
@@ -743,7 +770,11 @@ void TWorld::OnKeyDown(int cKey)
|
||||
}
|
||||
else if (cKey == Global::Keys[k_IncLocalBrakeLevel])
|
||||
{ // zahamowanie dowolnego pojazdu
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *temp = Global::DynamicNearest();
|
||||
#else
|
||||
TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false ) );
|
||||
#endif
|
||||
if (temp)
|
||||
{
|
||||
if (Global::ctrlState)
|
||||
@@ -762,7 +793,11 @@ void TWorld::OnKeyDown(int cKey)
|
||||
}
|
||||
else if (cKey == Global::Keys[k_DecLocalBrakeLevel])
|
||||
{ // odhamowanie dowolnego pojazdu
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *temp = Global::DynamicNearest();
|
||||
#else
|
||||
TDynamicObject *temp = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 20, false ) );
|
||||
#endif
|
||||
if (temp)
|
||||
{
|
||||
if (Global::ctrlState)
|
||||
@@ -915,20 +950,7 @@ void TWorld::FollowView(bool wycisz) {
|
||||
DistantView();
|
||||
};
|
||||
|
||||
bool TWorld::Update()
|
||||
{
|
||||
#ifdef USE_SCENERY_MOVING
|
||||
vector3 tmpvector = Global::GetCameraPosition();
|
||||
tmpvector = vector3(-int(tmpvector.x) + int(tmpvector.x) % 10000,
|
||||
-int(tmpvector.y) + int(tmpvector.y) % 10000,
|
||||
-int(tmpvector.z) + int(tmpvector.z) % 10000);
|
||||
if (tmpvector.x || tmpvector.y || tmpvector.z)
|
||||
{
|
||||
WriteLog("Moving scenery");
|
||||
Ground.MoveGroundNode(tmpvector);
|
||||
WriteLog("Scenery moved");
|
||||
};
|
||||
#endif
|
||||
bool TWorld::Update() {
|
||||
|
||||
Timer::UpdateTimers(Global::iPause != 0);
|
||||
|
||||
@@ -955,7 +977,7 @@ bool TWorld::Update()
|
||||
/*
|
||||
fTimeBuffer += dt; //[s] dodanie czasu od poprzedniej ramki
|
||||
*/
|
||||
m_primaryupdateaccumulator += dt;
|
||||
// m_primaryupdateaccumulator += dt; // unused for the time being
|
||||
m_secondaryupdateaccumulator += dt;
|
||||
/*
|
||||
if (fTimeBuffer >= fMaxDt) // jest co najmniej jeden krok; normalnie 0.01s
|
||||
@@ -999,21 +1021,26 @@ bool TWorld::Update()
|
||||
dt = dt / iterations; // Ra: fizykę lepiej by było przeliczać ze stałym krokiem
|
||||
*/
|
||||
}
|
||||
auto const stepdeltatime { dt / updatecount };
|
||||
// NOTE: updates are limited to 20, but dt is distributed over potentially many more iterations
|
||||
// this means at count > 20 simulation and render are going to desync. is that right?
|
||||
// NOTE: experimentally changing this to prevent the desync.
|
||||
// TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
if( true == Global::FullPhysics ) {
|
||||
// default calculation mode, each step calculated separately
|
||||
for( int updateidx = 0; updateidx < updatecount; ++updateidx ) {
|
||||
Ground.Update( dt / updatecount, 1 );
|
||||
// mixed calculation mode, steps calculated in ~0.05s chunks
|
||||
while( updatecount >= 5 ) {
|
||||
Ground.Update( stepdeltatime, 5 );
|
||||
updatecount -= 5;
|
||||
}
|
||||
if( updatecount ) {
|
||||
Ground.Update( stepdeltatime, updatecount );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// slightly simplified calculation mode; can lead to errors
|
||||
Ground.Update( dt / updatecount, updatecount );
|
||||
// simplified calculation mode; faster but can lead to errors
|
||||
Ground.Update( stepdeltatime, updatecount );
|
||||
}
|
||||
|
||||
// yB dodał przyspieszacz fizyki
|
||||
if( (true == DebugModeFlag)
|
||||
&& (true == Global::bActive) // nie przyspieszać, gdy jedzie w tle :)
|
||||
@@ -1024,8 +1051,24 @@ bool TWorld::Update()
|
||||
Ground.Update( dt, 1 );
|
||||
Ground.Update( dt, 1 ); // 5 razy
|
||||
}
|
||||
// secondary fixed step simulation time routines
|
||||
#else
|
||||
if( true == Global::FullPhysics ) {
|
||||
// mixed calculation mode, steps calculated in ~0.05s chunks
|
||||
while( updatecount >= 5 ) {
|
||||
simulation::State.update( stepdeltatime, 5 );
|
||||
updatecount -= 5;
|
||||
}
|
||||
if( updatecount ) {
|
||||
simulation::State.update( stepdeltatime, updatecount );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// simplified calculation mode; faster but can lead to errors
|
||||
simulation::State.update( stepdeltatime, updatecount );
|
||||
}
|
||||
#endif
|
||||
|
||||
// secondary fixed step simulation time routines
|
||||
while( m_secondaryupdateaccumulator >= m_secondaryupdaterate ) {
|
||||
|
||||
Global::tranTexts.Update(); // obiekt obsługujący stenogramy dźwięków na ekranie
|
||||
@@ -1065,11 +1108,12 @@ bool TWorld::Update()
|
||||
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.CheckQuery();
|
||||
Ground.Update_Hidden();
|
||||
#else
|
||||
simulation::Events.CheckQuery();
|
||||
simulation::Region->update();
|
||||
#endif
|
||||
|
||||
Ground.Update_Hidden();
|
||||
simulation::Lights.update();
|
||||
|
||||
// render time routines follow:
|
||||
@@ -1119,10 +1163,15 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
Camera.LookAt = Controlled->GetPosition();
|
||||
}
|
||||
else {
|
||||
TDynamicObject *d =
|
||||
Ground.DynamicNearest( Camera.Pos, 300 ); // szukaj w promieniu 300m
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TDynamicObject *d = Ground.DynamicNearest( Camera.Pos, 300 ); // szukaj w promieniu 300m
|
||||
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 ) );
|
||||
if( !d )
|
||||
d = std::get<TDynamicObject *>( simulation::Region->find_vehicle( Global::pCameraPosition, 1000, false ) ); // dalej szukanie, jesli bliżej nie ma
|
||||
#endif
|
||||
if( d && pDynamicNearest ) {
|
||||
// jeśli jakiś jest znaleziony wcześniej
|
||||
if( 100.0 * LengthSquared3( d->GetPosition() - Camera.Pos ) > LengthSquared3( pDynamicNearest->GetPosition() - Camera.Pos ) ) {
|
||||
@@ -1305,7 +1354,11 @@ TWorld::Update_UI() {
|
||||
// timetable
|
||||
TDynamicObject *tmp =
|
||||
( FreeFlyModeFlag ?
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.DynamicNearest( Camera.Pos ) :
|
||||
#else
|
||||
std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false ) ) :
|
||||
#endif
|
||||
Controlled ); // w trybie latania lokalizujemy wg mapy
|
||||
|
||||
if( tmp == nullptr ) { break; }
|
||||
@@ -1386,7 +1439,11 @@ TWorld::Update_UI() {
|
||||
|
||||
TDynamicObject *tmp =
|
||||
( FreeFlyModeFlag ?
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.DynamicNearest( Camera.Pos ) :
|
||||
#else
|
||||
std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false ) ) :
|
||||
#endif
|
||||
Controlled ); // w trybie latania lokalizujemy wg mapy
|
||||
|
||||
if( tmp != nullptr ) {
|
||||
@@ -1403,7 +1460,7 @@ TWorld::Update_UI() {
|
||||
uitextline1 +=
|
||||
"; C0:" +
|
||||
( tmp->PrevConnected ?
|
||||
tmp->PrevConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 0 ].CouplingFlag ) + (
|
||||
tmp->PrevConnected->name() + ":" + to_string( tmp->MoverParameters->Couplers[ 0 ].CouplingFlag ) + (
|
||||
tmp->MoverParameters->Couplers[ 0 ].CouplingFlag == 0 ?
|
||||
" (" + to_string( tmp->MoverParameters->Couplers[ 0 ].CoupleDist, 1 ) + " m)" :
|
||||
"" ) :
|
||||
@@ -1411,7 +1468,7 @@ TWorld::Update_UI() {
|
||||
uitextline1 +=
|
||||
" C1:" +
|
||||
( tmp->NextConnected ?
|
||||
tmp->NextConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 1 ].CouplingFlag ) + (
|
||||
tmp->NextConnected->name() + ":" + to_string( tmp->MoverParameters->Couplers[ 1 ].CouplingFlag ) + (
|
||||
tmp->MoverParameters->Couplers[ 1 ].CouplingFlag == 0 ?
|
||||
" (" + to_string( tmp->MoverParameters->Couplers[ 1 ].CoupleDist, 1 ) + " m)" :
|
||||
"" ) :
|
||||
@@ -1653,7 +1710,11 @@ TWorld::Update_UI() {
|
||||
|
||||
TDynamicObject *tmp =
|
||||
( FreeFlyModeFlag ?
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
Ground.DynamicNearest( Camera.Pos ) :
|
||||
#else
|
||||
std::get<TDynamicObject *>( simulation::Region->find_vehicle( Camera.Pos, 20, false ) ) :
|
||||
#endif
|
||||
Controlled ); // w trybie latania lokalizujemy wg mapy
|
||||
if( tmp == nullptr ) {
|
||||
break;
|
||||
@@ -1867,6 +1928,7 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
||||
Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
std::string(pRozkaz->cString + 11 + i, (unsigned)(pRozkaz->cString[10 + i])) +
|
||||
" rcvd");
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TGroundNode *t = Ground.DynamicFind(
|
||||
std::string(pRozkaz->cString + 11 + i,
|
||||
(unsigned)pRozkaz->cString[10 + i])); // nazwa pojazdu jest druga
|
||||
@@ -1878,6 +1940,19 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
||||
NULL, stopExt); // floaty są z przodu
|
||||
WriteLog("AI command: " + std::string(pRozkaz->cString + 9, i));
|
||||
}
|
||||
#else
|
||||
// nazwa pojazdu jest druga
|
||||
auto *vehicle = simulation::Vehicles.find( { pRozkaz->cString + 11 + i, (unsigned)pRozkaz->cString[ 10 + i ] } );
|
||||
if( ( vehicle != nullptr )
|
||||
&& ( vehicle->Mechanik != nullptr ) ) {
|
||||
vehicle->Mechanik->PutCommand(
|
||||
{ pRozkaz->cString + 9, static_cast<std::size_t>(i) },
|
||||
pRozkaz->fPar[0], pRozkaz->fPar[1],
|
||||
nullptr,
|
||||
stopExt ); // floaty są z przodu
|
||||
WriteLog("AI command: " + std::string(pRozkaz->cString + 9, i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 4: // badanie zajętości toru
|
||||
@@ -1920,6 +1995,7 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
||||
" rcvd");
|
||||
if (pRozkaz->cString[0]) // jeśli długość nazwy jest niezerowa
|
||||
{ // szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #7
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
TGroundNode *t;
|
||||
if (pRozkaz->cString[1] == '*')
|
||||
t = Ground.DynamicFind(
|
||||
@@ -1929,6 +2005,9 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
||||
pRozkaz->cString + 1, (unsigned)pRozkaz->cString[0])); // nazwa pojazdu
|
||||
if (t)
|
||||
Ground.WyslijNamiary(t); // wysłanie informacji o pojeździe
|
||||
#else
|
||||
// TODO: implement
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ // dla pustego wysyłamy ramki 6 z nazwami pojazdów AI (jeśli potrzebne wszystkie,
|
||||
@@ -1964,6 +2043,7 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
||||
CommLog(Now() + " " + to_string(pRozkaz->iComm) + " " +
|
||||
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) +
|
||||
" rcvd");
|
||||
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||
if( pRozkaz->cString[ 1 ] ) // jeśli długość nazwy jest niezerowa
|
||||
{ // szukamy pierwszego pojazdu o takiej nazwie i odsyłamy parametry ramką #13
|
||||
TGroundNode *t;
|
||||
@@ -1974,24 +2054,23 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
||||
t = Ground.DynamicFindAny(
|
||||
std::string( pRozkaz->cString + 2,
|
||||
(unsigned)pRozkaz->cString[ 1 ] ) ); // nazwa pojazdu
|
||||
if (t)
|
||||
{
|
||||
if( t ) {
|
||||
TDynamicObject *d = t->DynamicObject;
|
||||
while (d)
|
||||
{
|
||||
while( d ) {
|
||||
d->Damage( pRozkaz->cString[ 0 ] );
|
||||
d = d->Next(); // pozostałe też
|
||||
}
|
||||
d = t->DynamicObject->Prev();
|
||||
while (d)
|
||||
{
|
||||
while( d ) {
|
||||
d->Damage( pRozkaz->cString[ 0 ] );
|
||||
d = d->Prev(); // w drugą stronę też
|
||||
}
|
||||
Ground.WyslijUszkodzenia( t->asName, t->DynamicObject->MoverParameters->EngDmgFlag ); // zwrot informacji o pojeździe
|
||||
}
|
||||
}
|
||||
// Ground.IsolatedBusy(AnsiString(pRozkaz->cString+1,(unsigned)(pRozkaz->cString[0])));
|
||||
#else
|
||||
// TODO: implement
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
};
|
||||
@@ -2143,7 +2222,7 @@ void TWorld::ChangeDynamic() {
|
||||
Train->DynamicSet( temp );
|
||||
Controlled = temp;
|
||||
mvControlled = Controlled->ControlledFind()->MoverParameters;
|
||||
Global::asHumanCtrlVehicle = Train->Dynamic()->GetName();
|
||||
Global::asHumanCtrlVehicle = Train->Dynamic()->name();
|
||||
if( Train->Dynamic()->Mechanik ) // AI może sobie samo pójść
|
||||
if( !Train->Dynamic()->Mechanik->AIControllFlag ) // tylko jeśli ręcznie prowadzony
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ struct basic_vertex {
|
||||
glm::vec2 texture; // uv space
|
||||
|
||||
basic_vertex() = default;
|
||||
basic_vertex( glm::vec3 const &Position, glm::vec3 const &Normal, glm::vec2 const &Texture ) :
|
||||
basic_vertex( glm::vec3 Position, glm::vec3 Normal, glm::vec2 Texture ) :
|
||||
position( Position ), normal( Normal ), texture( Texture )
|
||||
{}
|
||||
void serialize( std::ostream& ) const;
|
||||
@@ -58,7 +58,7 @@ struct geometry_handle {
|
||||
geometry_handle() :
|
||||
bank( 0 ), chunk( 0 )
|
||||
{}
|
||||
geometry_handle( std::uint32_t const Bank, std::uint32_t const Chunk ) :
|
||||
geometry_handle( std::uint32_t Bank, std::uint32_t Chunk ) :
|
||||
bank( Bank ), chunk( Chunk )
|
||||
{}
|
||||
// methods
|
||||
@@ -121,7 +121,7 @@ protected:
|
||||
unsigned int type; // kind of geometry used by the chunk
|
||||
vertex_array vertices; // geometry data
|
||||
// NOTE: constructor doesn't copy provided vertex data, but moves it
|
||||
geometry_chunk( vertex_array &Vertices, unsigned int const Type ) :
|
||||
geometry_chunk( vertex_array &Vertices, unsigned int Type ) :
|
||||
type( Type )
|
||||
{
|
||||
vertices.swap( Vertices );
|
||||
|
||||
14
parser.cpp
14
parser.cpp
@@ -205,23 +205,21 @@ std::string cParser::readToken(bool ToLower, const char *Break)
|
||||
if (token.compare("include") == 0)
|
||||
{ // obsługa include
|
||||
std::string includefile = readToken(ToLower); // nazwa pliku
|
||||
if (LoadTraction ? true : ((includefile.find("tr/") == std::string::npos) &&
|
||||
(includefile.find("tra/") == std::string::npos)))
|
||||
{
|
||||
// std::string trtest2="niemaproblema"; //nazwa odporna na znalezienie "tr/"
|
||||
// if (trtest=="x") //jeśli nie wczytywać drutów
|
||||
// trtest2=includefile; //kopiowanie ścieżki do pliku
|
||||
if( ( true == LoadTraction )
|
||||
|| ( ( includefile.find( "tr/" ) == std::string::npos )
|
||||
&& ( includefile.find( "tra/" ) == std::string::npos ) ) ) {
|
||||
|
||||
std::string parameter = readToken(false); // w parametrach nie zmniejszamy
|
||||
while( (parameter.empty() == false)
|
||||
&& (parameter.compare("end") != 0) )
|
||||
{
|
||||
parameters.push_back(parameter);
|
||||
parameters.emplace_back(parameter);
|
||||
parameter = readToken(false);
|
||||
}
|
||||
// if (trtest2.find("tr/")!=0)
|
||||
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction);
|
||||
if (mIncludeParser->mSize <= 0)
|
||||
ErrorLog("Missed include: " + includefile);
|
||||
ErrorLog("Bad include: can't open file \"" + includefile + "\"" );
|
||||
}
|
||||
else {
|
||||
while( token.compare( "end" ) != 0 ) {
|
||||
|
||||
36
renderer.cpp
36
renderer.cpp
@@ -1602,7 +1602,17 @@ opengl_renderer::Render( scene::basic_region *Region ) {
|
||||
|
||||
m_sectionqueue.clear();
|
||||
m_cellqueue.clear();
|
||||
|
||||
/*
|
||||
for( auto *section : Region->sections( m_renderpass.camera.position(), m_renderpass.draw_range * Global::fDistanceFactor ) ) {
|
||||
#ifdef EU07_USE_DEBUG_CULLING
|
||||
if( m_worldcamera.camera.visible( section->m_area ) ) {
|
||||
#else
|
||||
if( m_renderpass.camera.visible( section->m_area ) ) {
|
||||
#endif
|
||||
m_sectionqueue.emplace_back( section );
|
||||
}
|
||||
}
|
||||
*/
|
||||
// build a list of region sections to render
|
||||
glm::vec3 const cameraposition { m_renderpass.camera.position() };
|
||||
auto const camerax = static_cast<int>( std::floor( cameraposition.x / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||
@@ -1903,11 +1913,22 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
||||
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::color:
|
||||
case rendermode::shadows:
|
||||
case rendermode::pickscenery: {
|
||||
// render
|
||||
case rendermode::shadows: {
|
||||
// opaque parts of instanced models
|
||||
for( auto *instance : cell->m_instancesopaque ) { Render( instance ); }
|
||||
// opaque parts of vehicles
|
||||
for( auto *path : cell->m_paths ) {
|
||||
for( auto *dynamic : path->Dynamics ) {
|
||||
Render( dynamic );
|
||||
}
|
||||
}
|
||||
}
|
||||
case rendermode::pickscenery: {
|
||||
// opaque parts of instanced models
|
||||
for( auto *instance : cell->m_instancesopaque ) {
|
||||
::glColor3fv( glm::value_ptr( pick_color( m_picksceneryitems.size() + 1 ) ) );
|
||||
Render( instance );
|
||||
}
|
||||
// TODO: add remaining content types
|
||||
break;
|
||||
}
|
||||
@@ -2863,7 +2884,12 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque
|
||||
|
||||
// translucent parts of instanced models
|
||||
for( auto *instance : cell->m_instancetranslucent ) { Render_Alpha( instance ); }
|
||||
// TODO: add remaining content types
|
||||
// translucent parts of vehicles
|
||||
for( auto *path : cell->m_paths ) {
|
||||
for( auto *dynamic : path->Dynamics ) {
|
||||
Render_Alpha( dynamic );
|
||||
}
|
||||
}
|
||||
|
||||
++first;
|
||||
}
|
||||
|
||||
425
scene.cpp
425
scene.cpp
@@ -10,11 +10,28 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stdafx.h"
|
||||
#include "scene.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "renderer.h"
|
||||
#include "logs.h"
|
||||
|
||||
namespace scene {
|
||||
|
||||
// legacy method, updates sounds and polls event launchers within radius around specified point
|
||||
void
|
||||
basic_cell::update() {
|
||||
/*
|
||||
// renderowanie obiektów aktywnych a niewidocznych
|
||||
for( auto node = subcell->nRenderHidden; node; node = node->nNext3 ) {
|
||||
node->RenderHidden();
|
||||
}
|
||||
*/
|
||||
// TBD, TODO: move to sound renderer
|
||||
for( auto *path : m_paths ) {
|
||||
// dźwięki pojazdów, również niewidocznych
|
||||
path->RenderDynSounds();
|
||||
}
|
||||
}
|
||||
|
||||
// adds provided shape to the cell
|
||||
void
|
||||
basic_cell::insert( shape_node Shape ) {
|
||||
@@ -90,6 +107,131 @@ basic_cell::insert( TAnimModel *Instance ) {
|
||||
}
|
||||
}
|
||||
|
||||
// registers provided path in the lookup directory of the cell
|
||||
void
|
||||
basic_cell::register_end( TTrack *Path ) {
|
||||
|
||||
m_directories.paths.emplace( Path );
|
||||
}
|
||||
|
||||
// registers provided traction piece in the lookup directory of the cell
|
||||
void
|
||||
basic_cell::register_end( TTraction *Traction ) {
|
||||
|
||||
m_directories.traction.emplace( 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 ) {
|
||||
|
||||
TDynamicObject *vehiclenearest { nullptr };
|
||||
float leastdistance { std::numeric_limits<float>::max() };
|
||||
float distance;
|
||||
float const distancecutoff { Radius * Radius }; // we'll ignore vehicles farther than this
|
||||
|
||||
for( auto *path : m_paths ) {
|
||||
for( auto *vehicle : path->Dynamics ) {
|
||||
if( ( true == Onlycontrolled )
|
||||
&& ( vehicle->Mechanik == nullptr ) ) {
|
||||
continue;
|
||||
}
|
||||
distance = glm::length2( glm::dvec3{ vehicle->GetPosition() } - Point );
|
||||
if( ( distance > distancecutoff )
|
||||
|| ( distance > leastdistance ) ){
|
||||
continue;
|
||||
}
|
||||
std::tie( vehiclenearest, leastdistance ) = std::tie( vehicle, distance );
|
||||
}
|
||||
}
|
||||
return std::tie( vehiclenearest, leastdistance );
|
||||
}
|
||||
|
||||
// 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>
|
||||
basic_cell::find( glm::dvec3 const &Point, TTrack const *Exclude ) {
|
||||
|
||||
Math3D::vector3 point { Point.x, Point.y, Point.z }; // sad workaround until math classes unification
|
||||
int endpointid;
|
||||
|
||||
for( auto *path : m_directories.paths ) {
|
||||
|
||||
if( path == Exclude ) { continue; }
|
||||
|
||||
endpointid = path->TestPoint( &point );
|
||||
if( endpointid >= 0 ) {
|
||||
|
||||
return std::tie( path, endpointid );
|
||||
}
|
||||
}
|
||||
return { nullptr, -1 };
|
||||
}
|
||||
|
||||
// finds a traction piece with one of its ends located in specified point. returns: located traction piece and id of the matching endpoint
|
||||
std::tuple<TTraction *, int>
|
||||
basic_cell::find( glm::dvec3 const &Point, TTraction const *Exclude ) {
|
||||
|
||||
int endpointid;
|
||||
|
||||
for( auto *traction : m_directories.traction ) {
|
||||
|
||||
if( traction == Exclude ) { continue; }
|
||||
|
||||
endpointid = traction->TestPoint( Point );
|
||||
if( endpointid >= 0 ) {
|
||||
|
||||
return std::tie( traction, endpointid );
|
||||
}
|
||||
}
|
||||
return { nullptr, -1 };
|
||||
}
|
||||
|
||||
// finds a traction piece located nearest to specified point, sharing section with specified other piece and powered in specified direction. returns: located traction piece
|
||||
std::tuple<TTraction *, int, float>
|
||||
basic_cell::find( glm::dvec3 const &Point, TTraction const *Other, int const Currentdirection ) {
|
||||
|
||||
TTraction
|
||||
*tractionnearest { nullptr };
|
||||
float
|
||||
distance,
|
||||
distancenearest { std::numeric_limits<float>::max() };
|
||||
int endpoint,
|
||||
endpointnearest { -1 };
|
||||
|
||||
for( auto *traction : m_directories.traction ) {
|
||||
|
||||
if( ( traction == Other )
|
||||
|| ( traction->psSection != Other->psSection )
|
||||
|| ( traction == Other->hvNext[ 0 ] )
|
||||
|| ( traction == Other->hvNext[ 1 ] ) ) {
|
||||
// ignore pieces from different sections, and ones connected to the other piece
|
||||
continue;
|
||||
}
|
||||
endpoint = (
|
||||
glm::dot( traction->vParametric, Other->vParametric ) >= 0.0 ?
|
||||
Currentdirection ^ 1 :
|
||||
Currentdirection );
|
||||
if( ( traction->psPower[ endpoint ] == nullptr )
|
||||
|| ( traction->fResistance[ endpoint ] < 0.0 ) ) {
|
||||
continue;
|
||||
}
|
||||
distance = glm::length2( traction->location() - Point );
|
||||
if( distance < distancenearest ) {
|
||||
std::tie( tractionnearest, endpointnearest, distancenearest ) = std::tie( traction, endpoint, distance );
|
||||
}
|
||||
}
|
||||
return { tractionnearest, endpointnearest, distancenearest };
|
||||
}
|
||||
|
||||
// sets center point of the section
|
||||
void
|
||||
basic_cell::center( glm::dvec3 Center ) {
|
||||
|
||||
m_area.center = Center;
|
||||
// NOTE: we should also update origin point for the contained nodes, but in practice we can skip this
|
||||
// as all nodes will be added only after the proper center point was set, and won't change
|
||||
}
|
||||
|
||||
// generates renderable version of held non-instanced geometry
|
||||
void
|
||||
basic_cell::create_geometry( geometrybank_handle const &Bank ) {
|
||||
@@ -104,16 +246,22 @@ basic_cell::create_geometry( geometrybank_handle const &Bank ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// sets center point of the section
|
||||
|
||||
|
||||
// legacy method, updates sounds and polls event launchers within radius around specified point
|
||||
void
|
||||
basic_cell::center( glm::dvec3 Center ) {
|
||||
basic_section::update( glm::dvec3 const &Location, float const Radius ) {
|
||||
|
||||
m_area.center = Center;
|
||||
// NOTE: we should also update origin point for the contained nodes, but in practice we can skip this
|
||||
// as all nodes will be added only after the proper center point was set, and won't change
|
||||
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 ) {
|
||||
// we reject cells which aren't within our area of interest
|
||||
cell.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// adds provided shape to the section
|
||||
void
|
||||
@@ -168,6 +316,96 @@ basic_section::insert( TAnimModel *Instance ) {
|
||||
cell( Instance->location() ).insert( Instance );
|
||||
}
|
||||
|
||||
// registers specified end point of the provided path in the lookup directory of the region
|
||||
void
|
||||
basic_section::register_end( TTrack *Path, glm::dvec3 const &Point ) {
|
||||
|
||||
cell( Point ).register_end( Path );
|
||||
}
|
||||
|
||||
// registers specified end point of the provided traction piece in the lookup directory of the region
|
||||
void
|
||||
basic_section::register_end( TTraction *Traction, glm::dvec3 const &Point ) {
|
||||
|
||||
cell( Point ).register_end( 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_section::find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled ) {
|
||||
|
||||
// go through sections within radius of interest, and pick the nearest candidate
|
||||
TDynamicObject
|
||||
*vehiclefound,
|
||||
*vehiclenearest { nullptr };
|
||||
float
|
||||
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 ) {
|
||||
continue;
|
||||
}
|
||||
std::tie( vehiclefound, distancefound ) = cell.find( Point, Radius, Onlycontrolled );
|
||||
if( ( vehiclefound != nullptr )
|
||||
&& ( distancefound < distancenearest ) ) {
|
||||
|
||||
std::tie( vehiclenearest, distancenearest ) = std::tie( vehiclefound, distancefound );
|
||||
}
|
||||
}
|
||||
return std::tie( vehiclenearest, distancenearest );
|
||||
}
|
||||
|
||||
// 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>
|
||||
basic_section::find( glm::dvec3 const &Point, TTrack const *Exclude ) {
|
||||
|
||||
return cell( Point ).find( Point, Exclude );
|
||||
}
|
||||
|
||||
// finds a traction piece with one of its ends located in specified point. returns: located traction piece and id of the matching endpoint
|
||||
std::tuple<TTraction *, int>
|
||||
basic_section::find( glm::dvec3 const &Point, TTraction const *Exclude ) {
|
||||
|
||||
return cell( Point ).find( Point, Exclude );
|
||||
}
|
||||
|
||||
// finds a traction piece located nearest to specified point, sharing section with specified other piece and powered in specified direction. returns: located traction piece
|
||||
std::tuple<TTraction *, int, float>
|
||||
basic_section::find( glm::dvec3 const &Point, TTraction const *Other, int const Currentdirection ) {
|
||||
|
||||
// go through sections within radius of interest, and pick the nearest candidate
|
||||
TTraction
|
||||
*tractionfound,
|
||||
*tractionnearest { nullptr };
|
||||
float
|
||||
distancefound,
|
||||
distancenearest { std::numeric_limits<float>::max() };
|
||||
int
|
||||
endpointfound,
|
||||
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 ) {
|
||||
continue;
|
||||
}
|
||||
std::tie( tractionfound, endpointfound, distancefound ) = cell.find( Point, Other, Currentdirection );
|
||||
if( ( tractionfound != nullptr )
|
||||
&& ( distancefound < distancenearest ) ) {
|
||||
|
||||
std::tie( tractionnearest, endpointnearest, distancenearest ) = std::tie( tractionfound, endpointfound, distancefound );
|
||||
}
|
||||
}
|
||||
return { tractionnearest, endpointnearest, distancenearest };
|
||||
}
|
||||
|
||||
// sets center point of the section
|
||||
void
|
||||
basic_section::center( glm::dvec3 Center ) {
|
||||
@@ -251,6 +489,17 @@ basic_region::~basic_region() {
|
||||
for( auto section : m_sections ) { if( section != nullptr ) { delete section; } }
|
||||
}
|
||||
|
||||
// legacy method, updates sounds and polls event launchers around camera
|
||||
void
|
||||
basic_region::update() {
|
||||
// render events and sounds from sectors near enough to the viewer
|
||||
auto const range = 2750.f; // audible range of 100 db sound
|
||||
auto const §ionlist = sections( Global::pCameraPosition, range );
|
||||
for( auto *section : sectionlist ) {
|
||||
section->update( Global::pCameraPosition, range );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) {
|
||||
|
||||
@@ -327,6 +576,11 @@ basic_region::insert_path( TTrack *Path, scratch_data &Scratchpad ) {
|
||||
// tracks are guaranteed to hava a name so we can skip the check
|
||||
ErrorLog( "Bad scenario: track node \"" + Path->name() + "\" placed in location outside region bounds (" + to_string( center ) + ")" );
|
||||
}
|
||||
// also register path ends in appropriate sections, for path merging lookups
|
||||
// TODO: clean this up during track refactoring
|
||||
for( auto &point : Path->endpoints() ) {
|
||||
register_path( Path, point );
|
||||
}
|
||||
}
|
||||
|
||||
// inserts provided track in the region
|
||||
@@ -344,6 +598,11 @@ basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) {
|
||||
// tracks are guaranteed to hava a name so we can skip the check
|
||||
ErrorLog( "Bad scenario: traction node \"" + Traction->name() + "\" placed in location outside region bounds (" + to_string( center ) + ")" );
|
||||
}
|
||||
// also register traction ends in appropriate sections, for path merging lookups
|
||||
// TODO: clean this up during track refactoring
|
||||
for( auto &point : Traction->endpoints() ) {
|
||||
register_traction( Traction, point );
|
||||
}
|
||||
}
|
||||
|
||||
// inserts provided instance of 3d model in the region
|
||||
@@ -363,6 +622,154 @@ basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad )
|
||||
}
|
||||
}
|
||||
|
||||
// inserts provided sound in the region
|
||||
void
|
||||
basic_region::insert_sound( TTextSound *Sound, scratch_data &Scratchpad ) {
|
||||
|
||||
/*
|
||||
// TODO: implement
|
||||
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||
auto center = Sound->location();
|
||||
|
||||
if( point_inside( center ) ) {
|
||||
// NOTE: nodes placed outside of region boundaries are discarded
|
||||
section( center ).insert( Instance );
|
||||
}
|
||||
else {
|
||||
// tracks are guaranteed to hava a name so we can skip the check
|
||||
ErrorLog( "Bad scenario: model node \"" + Instance->name() + "\" placed in location outside region bounds (" + to_string( center ) + ")" );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 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 ) {
|
||||
|
||||
auto const §ionlist = sections( Point, Radius );
|
||||
// go through sections within radius of interest, and pick the nearest candidate
|
||||
TDynamicObject
|
||||
*foundvehicle,
|
||||
*nearestvehicle { nullptr };
|
||||
float
|
||||
founddistance,
|
||||
nearestdistance { std::numeric_limits<float>::max() };
|
||||
|
||||
for( auto *section : sectionlist ) {
|
||||
std::tie( foundvehicle, founddistance ) = section->find( Point, Radius, Onlycontrolled );
|
||||
if( ( foundvehicle != nullptr )
|
||||
&& ( founddistance < nearestdistance ) ) {
|
||||
|
||||
std::tie( nearestvehicle, nearestdistance ) = std::tie( foundvehicle, founddistance );
|
||||
}
|
||||
}
|
||||
return std::tie( nearestvehicle, nearestdistance );
|
||||
}
|
||||
|
||||
// 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>
|
||||
basic_region::find_path( glm::dvec3 const &Point, TTrack const *Exclude ) {
|
||||
|
||||
// TBD: throw out of bounds exception instead of checks all over the place..?
|
||||
if( point_inside( Point ) ) {
|
||||
|
||||
return section( Point ).find( Point, Exclude );
|
||||
}
|
||||
|
||||
return std::make_tuple<TTrack *, int>( nullptr, -1 );
|
||||
}
|
||||
|
||||
// finds a traction piece with one of its ends located in specified point. returns: located traction piece and id of the matching endpoint
|
||||
std::tuple<TTraction *, int>
|
||||
basic_region::find_traction( glm::dvec3 const &Point, TTraction const *Exclude ) {
|
||||
|
||||
// TBD: throw out of bounds exception instead of checks all over the place..?
|
||||
if( point_inside( Point ) ) {
|
||||
|
||||
return section( Point ).find( Point, Exclude );
|
||||
}
|
||||
|
||||
return std::make_tuple<TTraction *, int>( nullptr, -1 );
|
||||
}
|
||||
|
||||
// finds a traction piece located nearest to specified point, sharing section with specified other piece and powered in specified direction. returns: located traction piece
|
||||
std::tuple<TTraction *, int>
|
||||
basic_region::find_traction( glm::dvec3 const &Point, TTraction const *Other, int const Currentdirection ) {
|
||||
|
||||
auto const §ionlist = sections( Point, 0.f );
|
||||
// go through sections within radius of interest, and pick the nearest candidate
|
||||
TTraction
|
||||
*tractionfound,
|
||||
*tractionnearest { nullptr };
|
||||
float
|
||||
distancefound,
|
||||
distancenearest { std::numeric_limits<float>::max() };
|
||||
int
|
||||
endpointfound,
|
||||
endpointnearest { -1 };
|
||||
|
||||
for( auto *section : sectionlist ) {
|
||||
std::tie( tractionfound, endpointfound, distancefound ) = section->find( Point, Other, Currentdirection );
|
||||
if( ( tractionfound != nullptr )
|
||||
&& ( distancefound < distancenearest ) ) {
|
||||
|
||||
std::tie( tractionnearest, endpointnearest, distancenearest ) = std::tie( tractionfound, endpointfound, distancefound );
|
||||
}
|
||||
}
|
||||
return { tractionnearest, endpointnearest };
|
||||
}
|
||||
|
||||
// finds sections inside specified sphere. returns: list of sections
|
||||
std::vector<basic_section *> const &
|
||||
basic_region::sections( glm::dvec3 const &Point, float const Radius ) {
|
||||
|
||||
m_scratchpad.sections.clear();
|
||||
|
||||
auto const centerx { static_cast<int>( std::floor( Point.x / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) ) };
|
||||
auto const centerz { static_cast<int>( std::floor( Point.z / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) ) };
|
||||
auto const sectioncount { 2 * static_cast<int>( std::ceil( Radius / EU07_SECTIONSIZE ) ) };
|
||||
|
||||
int const originx = centerx - sectioncount / 2;
|
||||
int const originz = centerz - sectioncount / 2;
|
||||
|
||||
auto const squaredradii { std::pow( ( 0.5 * M_SQRT2 * EU07_SECTIONSIZE + 0.25 * EU07_SECTIONSIZE ) + Radius, 2 ) };
|
||||
|
||||
for( int row = originz; row <= originz + sectioncount; ++row ) {
|
||||
if( row < 0 ) { continue; }
|
||||
if( row >= EU07_REGIONSIDESECTIONCOUNT ) { break; }
|
||||
for( int column = originx; column <= originx + sectioncount; ++column ) {
|
||||
if( column < 0 ) { continue; }
|
||||
if( column >= EU07_REGIONSIDESECTIONCOUNT ) { break; }
|
||||
|
||||
auto *section { m_sections[ row * EU07_REGIONSIDESECTIONCOUNT + column ] };
|
||||
if( ( section != nullptr )
|
||||
&& ( glm::length2( section->area().center - Point ) < squaredradii ) ) {
|
||||
|
||||
m_scratchpad.sections.emplace_back( section );
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_scratchpad.sections;
|
||||
}
|
||||
|
||||
// registers specified path in the lookup directory of a cell enclosing specified point
|
||||
void
|
||||
basic_region::register_path( TTrack *Path, glm::dvec3 const &Point ) {
|
||||
|
||||
if( point_inside( Point ) ) {
|
||||
section( Point ).register_end( Path, Point );
|
||||
}
|
||||
}
|
||||
|
||||
// registers specified end point of the provided traction piece in the lookup directory of the region
|
||||
void
|
||||
basic_region::register_traction( TTraction *Traction, glm::dvec3 const &Point ) {
|
||||
|
||||
if( point_inside( Point ) ) {
|
||||
section( Point ).register_end( Traction, Point );
|
||||
}
|
||||
}
|
||||
|
||||
// checks whether specified point is within boundaries of the region
|
||||
bool
|
||||
basic_region::point_inside( glm::dvec3 const &Location ) {
|
||||
@@ -566,8 +973,8 @@ basic_region::RaTriangleDivider( shape_node &Shape, std::deque<shape_node> &Shap
|
||||
basic_section &
|
||||
basic_region::section( glm::dvec3 const &Location ) {
|
||||
|
||||
auto const column = static_cast<int>( std::floor( Location.x / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||
auto const row = static_cast<int>( std::floor( Location.z / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||
auto const column { static_cast<int>( std::floor( Location.x / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) ) };
|
||||
auto const row { static_cast<int>( std::floor( Location.z / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) ) };
|
||||
|
||||
auto §ion =
|
||||
m_sections[
|
||||
|
||||
113
scene.h
113
scene.h
@@ -30,6 +30,18 @@ struct scratch_data {
|
||||
|
||||
std::stack<glm::dvec3> location_offset;
|
||||
glm::vec3 location_rotation;
|
||||
|
||||
struct trainset_data {
|
||||
|
||||
std::string name;
|
||||
std::string track;
|
||||
float offset { 0.f };
|
||||
float velocity { 0.f };
|
||||
std::vector<TDynamicObject *> vehicles;
|
||||
std::vector<std::int8_t> couplings;
|
||||
TDynamicObject * driver { nullptr };
|
||||
bool is_open { false };
|
||||
} trainset;
|
||||
};
|
||||
|
||||
// basic element of rudimentary partitioning scheme for the section. fixed size, no further subdivision
|
||||
@@ -40,6 +52,9 @@ class basic_cell {
|
||||
|
||||
public:
|
||||
// methods
|
||||
// legacy method, updates sounds and polls event launchers within radius around specified point
|
||||
void
|
||||
update();
|
||||
// adds provided shape to the cell
|
||||
void
|
||||
insert( shape_node Shape );
|
||||
@@ -52,18 +67,42 @@ public:
|
||||
// adds provided model instance to the cell
|
||||
void
|
||||
insert( TAnimModel *Instance );
|
||||
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||
// registers provided path in the lookup directory of the cell
|
||||
void
|
||||
create_geometry( geometrybank_handle const &Bank );
|
||||
register_end( TTrack *Path );
|
||||
// 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
|
||||
std::tuple<TDynamicObject *, float>
|
||||
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled );
|
||||
// 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 );
|
||||
// finds a traction piece with one of its ends located in specified point. returns: located traction piece and id of the matching endpoint
|
||||
std::tuple<TTraction *, int>
|
||||
find( glm::dvec3 const &Point, TTraction const *Exclude );
|
||||
// finds a traction piece located nearest to specified point, sharing section with specified other piece and powered in specified direction. returns: located traction piece
|
||||
std::tuple<TTraction *, int, float>
|
||||
find( glm::dvec3 const &Point, TTraction const *Other, int const Currentdirection );
|
||||
// sets center point of the cell
|
||||
void
|
||||
center( glm::dvec3 Center );
|
||||
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||
void
|
||||
create_geometry( geometrybank_handle const &Bank );
|
||||
// provides access to bounding area data
|
||||
bounding_area const &
|
||||
area() const {
|
||||
return m_area; }
|
||||
|
||||
private:
|
||||
// types
|
||||
using shapenode_sequence = std::vector<shape_node>;
|
||||
using path_sequence = std::vector<TTrack *>;
|
||||
using path_set = std::set<TTrack *>;
|
||||
using traction_sequence = std::vector<TTraction *>;
|
||||
using traction_set = std::set<TTraction *>;
|
||||
using instance_sequence = std::vector<TAnimModel *>;
|
||||
// members
|
||||
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) };
|
||||
@@ -75,6 +114,11 @@ private:
|
||||
instance_sequence m_instancesopaque;
|
||||
instance_sequence m_instancetranslucent;
|
||||
traction_sequence m_traction;
|
||||
// search helpers
|
||||
struct lookup_data {
|
||||
path_set paths;
|
||||
traction_set traction;
|
||||
} m_directories;
|
||||
};
|
||||
|
||||
// basic scene partitioning structure, holds terrain geometry and collection of cells
|
||||
@@ -84,6 +128,9 @@ class basic_section {
|
||||
|
||||
public:
|
||||
// methods
|
||||
// legacy method, updates sounds and polls event launchers within radius around specified point
|
||||
void
|
||||
update( glm::dvec3 const &Location, float const Radius );
|
||||
// adds provided shape to the section
|
||||
void
|
||||
insert( shape_node Shape );
|
||||
@@ -96,12 +143,34 @@ public:
|
||||
// adds provided model instance to the section
|
||||
void
|
||||
insert( TAnimModel *Instance );
|
||||
// generates renderable version of held non-instanced geometry
|
||||
// registers specified end point of the provided path in the lookup directory of the region
|
||||
void
|
||||
create_geometry();
|
||||
register_end( TTrack *Path, glm::dvec3 const &Point );
|
||||
// registers specified end point of the provided traction piece in the lookup directory of the region
|
||||
void
|
||||
register_end( TTraction *Traction, glm::dvec3 const &Point );
|
||||
// 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>
|
||||
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled );
|
||||
// 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 );
|
||||
// finds a traction piece with one of its ends located in specified point. returns: located traction piece and id of the matching endpoint
|
||||
std::tuple<TTraction *, int>
|
||||
find( glm::dvec3 const &Point, TTraction const *Exclude );
|
||||
// finds a traction piece located nearest to specified point, sharing section with specified other piece and powered in specified direction. returns: located traction piece
|
||||
std::tuple<TTraction *, int, float>
|
||||
find( glm::dvec3 const &Point, TTraction const *Other, int const Currentdirection );
|
||||
// sets center point of the section
|
||||
void
|
||||
center( glm::dvec3 Center );
|
||||
// generates renderable version of held non-instanced geometry
|
||||
void
|
||||
create_geometry();
|
||||
// provides access to bounding area data
|
||||
bounding_area const &
|
||||
area() const {
|
||||
return m_area; }
|
||||
|
||||
private:
|
||||
// types
|
||||
@@ -134,6 +203,9 @@ public:
|
||||
// destructor
|
||||
~basic_region();
|
||||
// methods
|
||||
// legacy method, updates sounds and polls event launchers around camera
|
||||
void
|
||||
update();
|
||||
// inserts provided shape in the region
|
||||
void
|
||||
insert_shape( shape_node Shape, scratch_data &Scratchpad );
|
||||
@@ -146,17 +218,45 @@ public:
|
||||
// inserts provided instance of 3d model in the region
|
||||
void
|
||||
insert_instance( TAnimModel *Instance, scratch_data &Scratchpad );
|
||||
|
||||
// inserts provided sound in the region
|
||||
void
|
||||
insert_sound( TTextSound *Sound, scratch_data &Scratchpad );
|
||||
// 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>
|
||||
find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled );
|
||||
// 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 );
|
||||
// finds a traction piece with one of its ends located in specified point. returns: located traction piece and id of the matching endpoint
|
||||
std::tuple<TTraction *, int>
|
||||
find_traction( glm::dvec3 const &Point, TTraction const *Exclude );
|
||||
// finds a traction piece located nearest to specified point, sharing section with specified other piece and powered in specified direction. returns: located traction piece
|
||||
std::tuple<TTraction *, int>
|
||||
find_traction( glm::dvec3 const &Point, TTraction const *Other, int const Currentdirection );
|
||||
// finds sections inside specified sphere. returns: list of sections
|
||||
std::vector<basic_section *> const &
|
||||
sections( glm::dvec3 const &Point, float const Radius );
|
||||
|
||||
private:
|
||||
// types
|
||||
using section_array = std::array<basic_section *, EU07_REGIONSIDESECTIONCOUNT * EU07_REGIONSIDESECTIONCOUNT>;
|
||||
|
||||
struct region_scratchpad {
|
||||
|
||||
std::vector<basic_section *> sections;
|
||||
};
|
||||
|
||||
// methods
|
||||
// registers specified end point of the provided path in the lookup directory of the region
|
||||
void
|
||||
register_path( TTrack *Path, glm::dvec3 const &Point );
|
||||
// registers specified end point of the provided traction piece in the lookup directory of the region
|
||||
void
|
||||
register_traction( TTraction *Traction, glm::dvec3 const &Point );
|
||||
// checks whether specified point is within boundaries of the region
|
||||
bool
|
||||
point_inside( glm::dvec3 const &Location );
|
||||
// trims provided shape to fit into a section, adds trimmed part at the end of provided list
|
||||
// legacy method, trims provided shape to fit into a section. adds trimmed part at the end of provided list, returns true if changes were made
|
||||
bool
|
||||
RaTriangleDivider( shape_node &Shape, std::deque<shape_node> &Shapes );
|
||||
// provides access to section enclosing specified point
|
||||
@@ -165,6 +265,7 @@ private:
|
||||
|
||||
// members
|
||||
section_array m_sections;
|
||||
region_scratchpad m_scratchpad;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace scene {
|
||||
|
||||
// restores content of the node from provded input stream
|
||||
shape_node &
|
||||
shape_node::deserialize( cParser &Input, node_data const &Nodedata ) {
|
||||
shape_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
||||
|
||||
// import common data
|
||||
m_name = Nodedata.name;
|
||||
@@ -291,6 +291,5 @@ basic_node::basic_node( scene::node_data const &Nodedata ) :
|
||||
std::numeric_limits<double>::max() );
|
||||
}
|
||||
|
||||
|
||||
} // editor
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
15
scenenode.h
15
scenenode.h
@@ -72,7 +72,7 @@ class node_manager {
|
||||
struct node_data {
|
||||
|
||||
double range_min { 0.0 };
|
||||
double range_max { 0.0 };
|
||||
double range_max { std::numeric_limits<double>::max() };
|
||||
std::string name;
|
||||
std::string type;
|
||||
};
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
// types
|
||||
struct shapenode_data {
|
||||
// placement and visibility
|
||||
bounding_area area; // bounding area, in world coordinates
|
||||
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
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
// methods
|
||||
// restores content of the node from provded input stream
|
||||
shape_node &
|
||||
deserialize( cParser &Input, node_data const &Nodedata );
|
||||
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( shape_node &Shape );
|
||||
@@ -229,12 +229,15 @@ public:
|
||||
std::string const &
|
||||
name() const {
|
||||
return m_name; }
|
||||
glm::dvec3 const &
|
||||
location() {
|
||||
return m_location; };
|
||||
void
|
||||
location( glm::dvec3 const Location ) {
|
||||
m_location = Location; }
|
||||
glm::dvec3 const &
|
||||
location() const {
|
||||
return m_location; };
|
||||
void
|
||||
visible( bool const Visible ) {
|
||||
m_visible = Visible; }
|
||||
bool
|
||||
visible() const {
|
||||
return m_visible; }
|
||||
|
||||
326
simulation.cpp
326
simulation.cpp
@@ -12,15 +12,19 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "globals.h"
|
||||
#include "logs.h"
|
||||
#include "uilayer.h"
|
||||
|
||||
namespace simulation {
|
||||
|
||||
state_manager State;
|
||||
event_manager Events;
|
||||
memory_manager Memory;
|
||||
memory_table Memory;
|
||||
path_table Paths;
|
||||
traction_table Traction;
|
||||
instance_manager Instances;
|
||||
powergridsource_table Powergrid;
|
||||
sound_table Sounds;
|
||||
instance_table Instances;
|
||||
vehicle_table Vehicles;
|
||||
light_array Lights;
|
||||
|
||||
scene::basic_region *Region { nullptr };
|
||||
@@ -44,6 +48,23 @@ state_manager::deserialize( std::string const &Scenariofile ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
state_manager::update( double const Deltatime, int Iterationcount ) {
|
||||
// aktualizacja animacji krokiem FPS: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń
|
||||
if (Deltatime == 0.0) {
|
||||
// jeśli załączona jest pauza, to tylko obsłużyć ruch w kabinie trzeba
|
||||
return;
|
||||
}
|
||||
|
||||
auto const totaltime { Deltatime * Iterationcount };
|
||||
// NOTE: we perform animations first, as they can determine factors like contact with powergrid
|
||||
TAnimModel::AnimUpdate( totaltime ); // wykonanie zakolejkowanych animacji
|
||||
|
||||
simulation::Powergrid.update( totaltime );
|
||||
simulation::Vehicles.update( Deltatime, Iterationcount );
|
||||
}
|
||||
|
||||
// restores class data from provided stream
|
||||
void
|
||||
state_manager::deserialize( cParser &Input ) {
|
||||
@@ -79,7 +100,11 @@ state_manager::deserialize( cParser &Input ) {
|
||||
for( auto &function : functionlist ) {
|
||||
functionmap.emplace( function.first, std::bind( function.second, this, std::ref( Input ), std::ref( importscratchpad ) ) );
|
||||
}
|
||||
|
||||
// deserialize content from the provided input
|
||||
auto
|
||||
timelast { std::chrono::steady_clock::now() },
|
||||
timenow { timelast };
|
||||
std::string token { Input.getToken<std::string>() };
|
||||
while( false == token.empty() ) {
|
||||
|
||||
@@ -91,6 +116,14 @@ state_manager::deserialize( cParser &Input ) {
|
||||
ErrorLog( "Bad scenario: unexpected token \"" + token + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
|
||||
}
|
||||
|
||||
timenow = std::chrono::steady_clock::now();
|
||||
if( std::chrono::duration_cast<std::chrono::milliseconds>( timenow - timelast ).count() >= 200 ) {
|
||||
timelast = timenow;
|
||||
glfwPollEvents();
|
||||
UILayer.set_progress( Input.getProgress(), Input.getFullProgress() );
|
||||
GfxRenderer.Render();
|
||||
}
|
||||
|
||||
token = Input.getToken<std::string>();
|
||||
}
|
||||
}
|
||||
@@ -218,6 +251,7 @@ state_manager::deserialize_firstinit( cParser &Input, scene::scratch_data &Scrat
|
||||
simulation::Paths.InitTracks();
|
||||
simulation::Traction.InitTraction();
|
||||
simulation::Events.InitEvents();
|
||||
simulation::Memory.InitCells();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -230,6 +264,8 @@ state_manager::deserialize_light( cParser &Input, scene::scratch_data &Scratchpa
|
||||
void
|
||||
state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||
|
||||
scene::node_data nodedata;
|
||||
// common data and node type indicator
|
||||
Input.getTokens( 4 );
|
||||
@@ -240,13 +276,27 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
>> nodedata.type;
|
||||
// type-based deserialization. not elegant but it'll do
|
||||
if( nodedata.type == "dynamic" ) {
|
||||
// TODO: implement
|
||||
skip_until( Input, "enddynamic" );
|
||||
|
||||
auto *vehicle { deserialize_dynamic( Input, Scratchpad, nodedata ) };
|
||||
// vehicle import can potentially fail
|
||||
if( vehicle == nullptr ) { return; }
|
||||
|
||||
if( false == simulation::Vehicles.insert( vehicle ) ) {
|
||||
|
||||
ErrorLog( "Bad scenario: vehicle with duplicate name, \"" + vehicle->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||
}
|
||||
|
||||
if( ( vehicle->MoverParameters->CategoryFlag == 1 ) // trains only
|
||||
&& ( ( vehicle->MoverParameters->SecuritySystem.SystemType != 0 )
|
||||
|| ( vehicle->MoverParameters->SandCapacity > 0.0 ) ) ) {
|
||||
// we check for presence of security system or sand load, as a way to determine whether the vehicle is a controllable engine
|
||||
// NOTE: this isn't 100% precise, e.g. middle EZT module comes with security system, while it has no lights, and some engines
|
||||
// don't have security systems fitted
|
||||
simulation::Lights.insert( vehicle );
|
||||
}
|
||||
}
|
||||
else if( nodedata.type == "track" ) {
|
||||
|
||||
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||
|
||||
auto *path { deserialize_path( Input, Scratchpad, nodedata ) };
|
||||
// duplicates of named tracks are currently experimentally allowed
|
||||
if( simulation::Paths.insert( path ) ) {
|
||||
@@ -262,10 +312,10 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
else if( nodedata.type == "traction" ) {
|
||||
|
||||
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||
|
||||
auto *traction { deserialize_traction( Input, Scratchpad, nodedata ) };
|
||||
// duplicates of named tracks are currently discarded
|
||||
// traction loading is optional
|
||||
if( traction == nullptr ) { return; }
|
||||
|
||||
if( simulation::Traction.insert( traction ) ) {
|
||||
simulation::Region->insert_traction( traction, Scratchpad );
|
||||
}
|
||||
@@ -274,18 +324,29 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
}
|
||||
else if( nodedata.type == "tractionpowersource" ) {
|
||||
// TODO: implement
|
||||
skip_until( Input, "end" );
|
||||
|
||||
auto *powersource { deserialize_tractionpowersource( Input, Scratchpad, nodedata ) };
|
||||
// traction loading is optional
|
||||
if( powersource == nullptr ) { return; }
|
||||
|
||||
if( simulation::Powergrid.insert( powersource ) ) {
|
||||
/*
|
||||
// TODO: implement this
|
||||
simulation::Region.insert_powersource( powersource, Scratchpad );
|
||||
*/
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad scenario: power grid source with duplicate name, \"" + powersource->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||
}
|
||||
}
|
||||
else if( nodedata.type == "model" ) {
|
||||
|
||||
if( nodedata.range_min < 0.0 ) {
|
||||
// convert and import 3d terrain
|
||||
// TODO: implement this
|
||||
}
|
||||
else {
|
||||
// regular instance of 3d mesh
|
||||
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||
|
||||
auto *instance { deserialize_model( Input, Scratchpad, nodedata ) };
|
||||
// model import can potentially fail
|
||||
if( instance == nullptr ) { return; }
|
||||
@@ -313,10 +374,7 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
else if( nodedata.type == "memcell" ) {
|
||||
|
||||
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||
|
||||
auto *memorycell { deserialize_memorycell( Input, Scratchpad, nodedata ) };
|
||||
// duplicates of named tracks are currently discarded
|
||||
if( simulation::Memory.insert( memorycell ) ) {
|
||||
/*
|
||||
// TODO: implement this
|
||||
@@ -325,10 +383,6 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad scenario: memory cell with duplicate name, \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||
/*
|
||||
delete memorycell;
|
||||
delete memorycellnode;
|
||||
*/
|
||||
}
|
||||
}
|
||||
else if( nodedata.type == "eventlauncher" ) {
|
||||
@@ -336,8 +390,14 @@ state_manager::deserialize_node( cParser &Input, scene::scratch_data &Scratchpad
|
||||
skip_until( Input, "end" );
|
||||
}
|
||||
else if( nodedata.type == "sound" ) {
|
||||
// TODO: implement
|
||||
skip_until( Input, "endsound" );
|
||||
|
||||
auto *sound { deserialize_sound( Input, Scratchpad, nodedata ) };
|
||||
if( simulation::Sounds.insert( sound ) ) {
|
||||
simulation::Region->insert_sound( sound, Scratchpad );
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad scenario: sound node with duplicate name, \"" + sound->m_name + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -417,14 +477,68 @@ state_manager::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad
|
||||
void
|
||||
state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// TODO: implement
|
||||
skip_until( Input, "endtrainset" );
|
||||
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() ) + ")" );
|
||||
}
|
||||
|
||||
Scratchpad.trainset = scene::scratch_data::trainset_data();
|
||||
Scratchpad.trainset.is_open = true;
|
||||
|
||||
Input.getTokens( 4 );
|
||||
Input
|
||||
>> Scratchpad.trainset.name
|
||||
>> Scratchpad.trainset.track
|
||||
>> Scratchpad.trainset.offset
|
||||
>> Scratchpad.trainset.velocity;
|
||||
}
|
||||
|
||||
void
|
||||
state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||
|
||||
// TODO: implement
|
||||
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 ) + ")" );
|
||||
Scratchpad.trainset.is_open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t vehicleindex { 0 };
|
||||
for( auto *vehicle : Scratchpad.trainset.vehicles ) {
|
||||
// go through list of vehicles in the trainset, coupling them together and checking for potential driver
|
||||
if( ( vehicle->Mechanik != nullptr )
|
||||
&& ( vehicle->Mechanik->Primary() ) ) {
|
||||
// primary driver will receive the timetable for this trainset
|
||||
Scratchpad.trainset.driver = vehicle;
|
||||
}
|
||||
if( vehicleindex > 0 ) {
|
||||
// from second vehicle on couple it with the previous one
|
||||
Scratchpad.trainset.vehicles[ vehicleindex - 1 ]->AttachPrev(
|
||||
vehicle,
|
||||
Scratchpad.trainset.couplings[ vehicleindex - 1 ] );
|
||||
}
|
||||
++vehicleindex;
|
||||
}
|
||||
|
||||
if( Scratchpad.trainset.driver != nullptr ) {
|
||||
// if present, send timetable to the driver
|
||||
// wysłanie komendy "Timetable" ustawia odpowiedni tryb jazdy
|
||||
auto *controller = Scratchpad.trainset.driver->Mechanik;
|
||||
controller->DirectionInitial();
|
||||
controller->PutCommand(
|
||||
"Timetable:" + Scratchpad.trainset.name,
|
||||
Scratchpad.trainset.velocity,
|
||||
0,
|
||||
nullptr );
|
||||
}
|
||||
if( Scratchpad.trainset.couplings.back() == coupling::faux ) {
|
||||
// jeśli ostatni pojazd ma sprzęg 0 to założymy mu końcówki blaszane (jak AI się odpali, to sobie poprawi)
|
||||
Scratchpad.trainset.vehicles.back()->RaLightsSet( -1, TMoverParameters::light::rearendsignals );
|
||||
}
|
||||
// all done
|
||||
Scratchpad.trainset.is_open = false;
|
||||
}
|
||||
|
||||
// creates path and its wrapper, restoring class data from provided stream
|
||||
@@ -448,6 +562,10 @@ state_manager::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad
|
||||
TTraction *
|
||||
state_manager::deserialize_traction( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
if( false == Global::bLoadTraction ) {
|
||||
skip_until( Input, "endtraction" );
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: refactor track and wrapper classes and their de/serialization. do offset and rotation after deserialization is done
|
||||
auto *traction = new TTraction( Nodedata );
|
||||
auto offset = (
|
||||
@@ -459,6 +577,22 @@ state_manager::deserialize_traction( cParser &Input, scene::scratch_data &Scratc
|
||||
return traction;
|
||||
}
|
||||
|
||||
TTractionPowerSource *
|
||||
state_manager::deserialize_tractionpowersource( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
if( false == Global::bLoadTraction ) {
|
||||
skip_until( Input, "end" );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *powersource = new TTractionPowerSource( Nodedata );
|
||||
powersource->Load( &Input );
|
||||
// adjust location
|
||||
powersource->location( transform( powersource->location(), Scratchpad ) );
|
||||
|
||||
return powersource;
|
||||
}
|
||||
|
||||
TMemCell *
|
||||
state_manager::deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
@@ -481,7 +615,6 @@ state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpa
|
||||
>> location.y
|
||||
>> location.z
|
||||
>> rotation.y;
|
||||
// adjust location
|
||||
|
||||
auto *instance = new TAnimModel( Nodedata );
|
||||
instance->RaAnglesSet( Scratchpad.location_rotation + rotation ); // dostosowanie do pochylania linii
|
||||
@@ -495,6 +628,147 @@ state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpa
|
||||
return instance;
|
||||
}
|
||||
|
||||
TDynamicObject *
|
||||
state_manager::deserialize_dynamic( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
if( false == Scratchpad.trainset.is_open ) {
|
||||
// part of trainset data is used when loading standalone vehicles, so clear it just in case
|
||||
Scratchpad.trainset = scene::scratch_data::trainset_data();
|
||||
}
|
||||
auto const inputline { Input.Line() }; // cache in case of errors
|
||||
// basic attributes
|
||||
auto const datafolder { Input.getToken<std::string>() };
|
||||
auto const skinfile { Input.getToken<std::string>() };
|
||||
auto const mmdfile { Input.getToken<std::string>() };
|
||||
auto const pathname = (
|
||||
Scratchpad.trainset.is_open ?
|
||||
Scratchpad.trainset.track :
|
||||
Input.getToken<std::string>() );
|
||||
auto const offset { Input.getToken<double>( false ) };
|
||||
auto const drivertype { Input.getToken<std::string>() };
|
||||
auto const couplingparams = (
|
||||
Scratchpad.trainset.is_open ?
|
||||
Input.getToken<std::string>() :
|
||||
"3" );
|
||||
auto const velocity = (
|
||||
Scratchpad.trainset.is_open ?
|
||||
Scratchpad.trainset.velocity :
|
||||
Input.getToken<float>( false ) );
|
||||
// extract coupling type and optional parameters
|
||||
auto const couplingparamsplit = couplingparams.find( '.' );
|
||||
auto coupling = (
|
||||
couplingparamsplit != std::string::npos ?
|
||||
std::atoi( couplingparams.substr( 0, couplingparamsplit ).c_str() ) :
|
||||
std::atoi( couplingparams.c_str() ) );
|
||||
if( coupling < 0 ) {
|
||||
// sprzęg zablokowany (pojazdy nierozłączalne przy manewrach)
|
||||
coupling = ( -coupling ) | coupling::permanent;
|
||||
}
|
||||
if( ( offset != -1.0 )
|
||||
&& ( std::abs( offset ) > 0.5 ) ) { // maksymalna odległość między sprzęgami - do przemyślenia
|
||||
// likwidacja sprzęgu, jeśli odległość zbyt duża - to powinno być uwzględniane w fizyce sprzęgów...
|
||||
coupling = 0;
|
||||
}
|
||||
auto const params = (
|
||||
couplingparamsplit != std::string::npos ?
|
||||
couplingparams.substr( couplingparamsplit + 1 ) :
|
||||
"" );
|
||||
// load amount and type
|
||||
auto loadcount { Input.getToken<int>( false ) };
|
||||
auto loadtype = (
|
||||
loadcount ?
|
||||
Input.getToken<std::string>() :
|
||||
"" );
|
||||
if( loadtype == "enddynamic" ) {
|
||||
// idiotoodporność: ładunek bez podanego typu nie liczy się jako ładunek
|
||||
loadcount = 0;
|
||||
loadtype = "";
|
||||
}
|
||||
|
||||
auto *path = simulation::Paths.find( pathname );
|
||||
if( path == nullptr ) {
|
||||
|
||||
ErrorLog( "Bad scenario: vehicle \"" + Nodedata.name + "\" placed on nonexistent path \"" + pathname + "\" in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||
skip_until( Input, "enddynamic" );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if( ( true == Scratchpad.trainset.vehicles.empty() ) // jeśli pierwszy pojazd,
|
||||
&& ( false == path->asEvent0Name.empty() ) // tor ma Event0
|
||||
&& ( std::abs( velocity ) <= 1.f ) // a skład stoi
|
||||
&& ( Scratchpad.trainset.offset >= 0.0 ) // ale może nie sięgać na owy tor
|
||||
&& ( Scratchpad.trainset.offset < 8.0 ) ) { // i raczej nie sięga
|
||||
// przesuwamy około pół EU07 dla wstecznej zgodności
|
||||
Scratchpad.trainset.offset = 8.0;
|
||||
}
|
||||
|
||||
auto *vehicle = new TDynamicObject();
|
||||
|
||||
auto const length =
|
||||
vehicle->Init(
|
||||
Nodedata.name,
|
||||
datafolder, skinfile, mmdfile,
|
||||
path,
|
||||
( offset == -1.0 ?
|
||||
Scratchpad.trainset.offset :
|
||||
Scratchpad.trainset.offset - offset ),
|
||||
drivertype,
|
||||
velocity,
|
||||
Scratchpad.trainset.name,
|
||||
loadcount, loadtype,
|
||||
( offset == -1.0 ),
|
||||
params );
|
||||
|
||||
if( length != 0.0 ) { // zero oznacza błąd
|
||||
// przesunięcie dla kolejnego, minus bo idziemy w stronę punktu 1
|
||||
Scratchpad.trainset.offset -= length;
|
||||
// automatically establish permanent connections for couplers which specify them in their definitions
|
||||
if( ( coupling != 0 )
|
||||
&& ( vehicle->MoverParameters->Couplers[ ( offset == -1.0 ? 0 : 1 ) ].AllowedFlag & coupling::permanent ) ) {
|
||||
coupling |= coupling::permanent;
|
||||
}
|
||||
if( true == Scratchpad.trainset.is_open ) {
|
||||
Scratchpad.trainset.vehicles.emplace_back( vehicle );
|
||||
Scratchpad.trainset.couplings.emplace_back( coupling );
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete vehicle;
|
||||
skip_until( Input, "enddynamic" );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto const destination { Input.getToken<std::string>() };
|
||||
if( destination != "enddynamic" ) {
|
||||
// optional vehicle destination parameter
|
||||
vehicle->asDestination = Input.getToken<std::string>();
|
||||
skip_until( Input, "enddynamic" );
|
||||
}
|
||||
|
||||
return vehicle;
|
||||
}
|
||||
|
||||
TTextSound *
|
||||
state_manager::deserialize_sound( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||
|
||||
glm::dvec3 location;
|
||||
Input.getTokens( 3 );
|
||||
Input
|
||||
>> location.x
|
||||
>> location.y
|
||||
>> location.z;
|
||||
// adjust location
|
||||
location = transform( location, Scratchpad );
|
||||
|
||||
auto const soundname { Input.getToken<std::string>() };
|
||||
auto *sound = new TTextSound( soundname, Nodedata.range_max, location.x, location.y, location.z, false, false, Nodedata.range_min );
|
||||
sound->name( Nodedata.name );
|
||||
|
||||
skip_until( Input, "endsound" );
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
// skips content of stream until specified token
|
||||
void
|
||||
state_manager::skip_until( cParser &Input, std::string const &Token ) {
|
||||
|
||||
21
simulation.h
21
simulation.h
@@ -9,14 +9,18 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "parser.h"
|
||||
#include "scene.h"
|
||||
#include "event.h"
|
||||
#include "memcell.h"
|
||||
#include "track.h"
|
||||
#include "traction.h"
|
||||
#include "tractionpower.h"
|
||||
#include "realsound.h"
|
||||
#include "animmodel.h"
|
||||
#include "scene.h"
|
||||
#include "dynobj.h"
|
||||
#include "driver.h"
|
||||
#include "lightarray.h"
|
||||
#include "parser.h"
|
||||
|
||||
namespace simulation {
|
||||
|
||||
@@ -26,6 +30,9 @@ public:
|
||||
// types
|
||||
|
||||
// methods
|
||||
// legacy method, calculates changes in simulation state over specified time
|
||||
void
|
||||
update( double dt, int iter );
|
||||
bool
|
||||
deserialize( std::string const &Scenariofile );
|
||||
|
||||
@@ -51,8 +58,11 @@ private:
|
||||
void deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad );
|
||||
TTrack * deserialize_path( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
TTraction * deserialize_traction( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
TTractionPowerSource * deserialize_tractionpowersource( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
TMemCell * deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
TAnimModel * deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
TDynamicObject * deserialize_dynamic( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
TTextSound * deserialize_sound( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||
// skips content of stream until specified token
|
||||
void skip_until( cParser &Input, std::string const &Token );
|
||||
// transforms provided location by specifed rotation and offset
|
||||
@@ -61,10 +71,13 @@ private:
|
||||
|
||||
extern state_manager State;
|
||||
extern event_manager Events;
|
||||
extern memory_manager Memory;
|
||||
extern memory_table Memory;
|
||||
extern path_table Paths;
|
||||
extern traction_table Traction;
|
||||
extern instance_manager Instances;
|
||||
extern powergridsource_table Powergrid;
|
||||
extern sound_table Sounds;
|
||||
extern instance_table Instances;
|
||||
extern vehicle_table Vehicles;
|
||||
extern light_array Lights;
|
||||
|
||||
extern scene::basic_region *Region;
|
||||
|
||||
Reference in New Issue
Block a user