mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 14:29:18 +02:00
tmj merge
This commit is contained in:
@@ -15,15 +15,12 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "AnimModel.h"
|
#include "AnimModel.h"
|
||||||
|
|
||||||
#include "Globals.h"
|
|
||||||
#include "Logs.h"
|
|
||||||
#include "usefull.h"
|
|
||||||
#include "McZapkie/mctools.h"
|
|
||||||
#include "Timer.h"
|
|
||||||
#include "MdlMngr.h"
|
#include "MdlMngr.h"
|
||||||
// McZapkie:
|
#include "simulation.h"
|
||||||
#include "renderer.h"
|
#include "Globals.h"
|
||||||
//---------------------------------------------------------------------------
|
#include "Timer.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
|
||||||
TAnimContainer *TAnimModel::acAnimList = NULL;
|
TAnimContainer *TAnimModel::acAnimList = NULL;
|
||||||
|
|
||||||
TAnimAdvanced::TAnimAdvanced(){};
|
TAnimAdvanced::TAnimAdvanced(){};
|
||||||
@@ -232,9 +229,10 @@ void TAnimContainer::UpdateModel() {
|
|||||||
fTranslateSpeed = 0.0; // wyłączenie przeliczania wektora
|
fTranslateSpeed = 0.0; // wyłączenie przeliczania wektora
|
||||||
if (LengthSquared3(vTranslation) <= 0.0001) // jeśli jest w punkcie początkowym
|
if (LengthSquared3(vTranslation) <= 0.0001) // jeśli jest w punkcie początkowym
|
||||||
iAnim &= ~2; // wyłączyć zmianę pozycji submodelu
|
iAnim &= ~2; // wyłączyć zmianę pozycji submodelu
|
||||||
if (evDone)
|
if( evDone ) {
|
||||||
Global::AddToQuery(evDone, NULL); // wykonanie eventu informującego o
|
// wykonanie eventu informującego o zakończeniu
|
||||||
// zakończeniu
|
simulation::Events.AddToQuery( evDone, nullptr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fRotateSpeed != 0.0)
|
if (fRotateSpeed != 0.0)
|
||||||
@@ -299,9 +297,10 @@ void TAnimContainer::UpdateModel() {
|
|||||||
if (!anim)
|
if (!anim)
|
||||||
{ // nie potrzeba przeliczać już
|
{ // nie potrzeba przeliczać już
|
||||||
fRotateSpeed = 0.0;
|
fRotateSpeed = 0.0;
|
||||||
if (evDone)
|
if( evDone ) {
|
||||||
Global::AddToQuery(evDone, NULL); // wykonanie eventu informującego o
|
// wykonanie eventu informującego o zakończeniu
|
||||||
// zakończeniu
|
simulation::Events.AddToQuery( evDone, nullptr );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( fAngleSpeed != 0.f ) {
|
if( fAngleSpeed != 0.f ) {
|
||||||
@@ -330,7 +329,7 @@ void TAnimContainer::PrepareModel()
|
|||||||
fAngleSpeed = 0.0; // wyłączenie przeliczania wektora
|
fAngleSpeed = 0.0; // wyłączenie przeliczania wektora
|
||||||
if( evDone ) {
|
if( evDone ) {
|
||||||
// wykonanie eventu informującego o zakończeniu
|
// wykonanie eventu informującego o zakończeniu
|
||||||
Global::AddToQuery( evDone, NULL );
|
simulation::Events.AddToQuery( evDone, nullptr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -406,23 +405,20 @@ void TAnimContainer::EventAssign(TEvent *ev)
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
TAnimModel::TAnimModel()
|
TAnimModel::TAnimModel( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {
|
||||||
{
|
// TODO: wrap these in a tuple and move to underlying model
|
||||||
pRoot = NULL;
|
for( int index = 0; index < iMaxNumLights; ++index ) {
|
||||||
pModel = NULL;
|
LightsOn[ index ] = LightsOff[ index ] = nullptr; // normalnie nie ma
|
||||||
iNumLights = 0;
|
lsLights[ index ] = ls_Off; // a jeśli są, to wyłączone
|
||||||
fBlinkTimer = 0;
|
}
|
||||||
|
}
|
||||||
for (int i = 0; i < iMaxNumLights; ++i)
|
|
||||||
{
|
TAnimModel::TAnimModel() {
|
||||||
LightsOn[i] = LightsOff[i] = nullptr; // normalnie nie ma
|
// TODO: wrap these in a tuple and move to underlying model
|
||||||
lsLights[i] = ls_Off; // a jeśli są, to wyłączone
|
for( int index = 0; index < iMaxNumLights; ++index ) {
|
||||||
|
LightsOn[index] = LightsOff[index] = nullptr; // normalnie nie ma
|
||||||
|
lsLights[index] = ls_Off; // a jeśli są, to wyłączone
|
||||||
}
|
}
|
||||||
vAngle.x = vAngle.y = vAngle.z = 0.0; // zerowanie obrotów egzemplarza
|
|
||||||
pAdvanced = NULL; // nie ma zaawansowanej animacji
|
|
||||||
fDark = 0.25f; // standardowy próg zaplania
|
|
||||||
fOnTime = 0.66f;
|
|
||||||
fOffTime = fOnTime + 0.66f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TAnimModel::~TAnimModel()
|
TAnimModel::~TAnimModel()
|
||||||
@@ -572,6 +568,15 @@ void TAnimModel::RaAnimate( unsigned int const Framestamp ) {
|
|||||||
m_framestamp = Framestamp;
|
m_framestamp = Framestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// calculates piece's bounding radius
|
||||||
|
void
|
||||||
|
TAnimModel::radius_() {
|
||||||
|
|
||||||
|
if( pModel != nullptr ) {
|
||||||
|
m_area.radius = pModel->bounding_radius();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TAnimModel::RaPrepare()
|
void TAnimModel::RaPrepare()
|
||||||
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
|
{ // ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
|
||||||
bool state; // stan światła
|
bool state; // stan światła
|
||||||
@@ -762,22 +767,28 @@ void TAnimModel::LightSet(int n, float v)
|
|||||||
{ // ustawienie światła (n) na wartość (v)
|
{ // ustawienie światła (n) na wartość (v)
|
||||||
if (n >= iMaxNumLights)
|
if (n >= iMaxNumLights)
|
||||||
return; // przekroczony zakres
|
return; // przekroczony zakres
|
||||||
lsLights[n] = TLightState(int(v));
|
lsLights[ n ] = TLightState( static_cast<int>( v ) );
|
||||||
switch (lsLights[n])
|
switch( lsLights[ n ] ) {
|
||||||
{ // interpretacja ułamka zależnie od typu
|
// interpretacja ułamka zależnie od typu
|
||||||
case 0: // ustalenie czasu migotania, t<1s (f>1Hz), np. 0.1 => t=0.1 (f=10Hz)
|
case ls_Off: {
|
||||||
|
// ustalenie czasu migotania, t<1s (f>1Hz), np. 0.1 => t=0.1 (f=10Hz)
|
||||||
break;
|
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;
|
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;
|
break;
|
||||||
case 3: // zapalenie świateł zależne od oświetlenia scenerii
|
}
|
||||||
if (v > 3.0)
|
case ls_Dark: {
|
||||||
fDark = v - 3.0; // ustawienie indywidualnego progu zapalania
|
// zapalenie świateł zależne od oświetlenia scenerii
|
||||||
else
|
if( v > 3.0 ) { fDark = v - 3.0; } // ustawienie indywidualnego progu zapalania
|
||||||
fDark = 0.25; // standardowy próg zaplania
|
else { fDark = DefaultDarkThresholdLevel; } // standardowy próg zaplania
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void TAnimModel::AnimUpdate(double dt)
|
void TAnimModel::AnimUpdate(double dt)
|
||||||
|
|||||||
138
AnimModel.h
138
AnimModel.h
@@ -19,15 +19,16 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "DynObj.h"
|
#include "DynObj.h"
|
||||||
|
|
||||||
const int iMaxNumLights = 8;
|
const int iMaxNumLights = 8;
|
||||||
|
float const DefaultDarkThresholdLevel { 0.325f };
|
||||||
|
|
||||||
// typy stanu świateł
|
// typy stanu świateł
|
||||||
typedef enum
|
enum TLightState
|
||||||
{
|
{
|
||||||
ls_Off = 0, // zgaszone
|
ls_Off = 0, // zgaszone
|
||||||
ls_On = 1, // zapalone
|
ls_On = 1, // zapalone
|
||||||
ls_Blink = 2, // migające
|
ls_Blink = 2, // migające
|
||||||
ls_Dark = 3 // Ra: zapalajce się automatycznie, gdy zrobi się ciemno
|
ls_Dark = 3 // Ra: zapalajce się automatycznie, gdy zrobi się ciemno
|
||||||
} TLightState;
|
};
|
||||||
|
|
||||||
class TAnimVocaloidFrame
|
class TAnimVocaloidFrame
|
||||||
{ // ramka animacji typu Vocaloid Motion Data z programu MikuMikuDance
|
{ // ramka animacji typu Vocaloid Motion Data z programu MikuMikuDance
|
||||||
@@ -77,16 +78,9 @@ class TAnimContainer
|
|||||||
TAnimContainer();
|
TAnimContainer();
|
||||||
~TAnimContainer();
|
~TAnimContainer();
|
||||||
bool Init(TSubModel *pNewSubModel);
|
bool Init(TSubModel *pNewSubModel);
|
||||||
// std::string inline GetName() { return
|
inline
|
||||||
// std::string(pSubModel?pSubModel->asName.c_str():""); };
|
std::string NameGet() {
|
||||||
// std::string inline GetName() { return std::string(pSubModel?pSubModel->pName:"");
|
return (pSubModel ? pSubModel->pName : ""); };
|
||||||
// };
|
|
||||||
std::string NameGet()
|
|
||||||
{
|
|
||||||
return (pSubModel ? pSubModel->pName : "");
|
|
||||||
};
|
|
||||||
// void SetRotateAnim(vector3 vNewRotateAxis, double fNewDesiredAngle, double
|
|
||||||
// fNewRotateSpeed, bool bResetAngle=false);
|
|
||||||
void SetRotateAnim(vector3 vNewRotateAngles, double fNewRotateSpeed);
|
void SetRotateAnim(vector3 vNewRotateAngles, double fNewRotateSpeed);
|
||||||
void SetTranslateAnim(vector3 vNewTranslate, double fNewSpeed);
|
void SetTranslateAnim(vector3 vNewTranslate, double fNewSpeed);
|
||||||
void AnimSetVMD(double fNewSpeed);
|
void AnimSetVMD(double fNewSpeed);
|
||||||
@@ -94,24 +88,20 @@ class TAnimContainer
|
|||||||
void UpdateModel();
|
void UpdateModel();
|
||||||
void UpdateModelIK();
|
void UpdateModelIK();
|
||||||
bool InMovement(); // czy w trakcie animacji?
|
bool InMovement(); // czy w trakcie animacji?
|
||||||
double AngleGet()
|
inline
|
||||||
{
|
double AngleGet() {
|
||||||
return vRotateAngles.z;
|
return vRotateAngles.z; }; // jednak ostatnia, T3D ma inny układ
|
||||||
}; // jednak ostatnia, T3D ma inny układ
|
inline
|
||||||
vector3 TransGet()
|
vector3 TransGet() {
|
||||||
{
|
return vector3(-vTranslation.x, vTranslation.z, vTranslation.y); }; // zmiana, bo T3D ma inny układ
|
||||||
return vector3(-vTranslation.x, vTranslation.z, vTranslation.y);
|
inline
|
||||||
}; // zmiana, bo T3D ma inny układ
|
void WillBeAnimated() {
|
||||||
void WillBeAnimated()
|
|
||||||
{
|
|
||||||
if (pSubModel)
|
if (pSubModel)
|
||||||
pSubModel->WillBeAnimated();
|
pSubModel->WillBeAnimated(); };
|
||||||
};
|
|
||||||
void EventAssign(TEvent *ev);
|
void EventAssign(TEvent *ev);
|
||||||
TEvent * Event()
|
inline
|
||||||
{
|
TEvent * Event() {
|
||||||
return evDone;
|
return evDone; };
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TAnimAdvanced
|
class TAnimAdvanced
|
||||||
@@ -129,15 +119,59 @@ class TAnimAdvanced
|
|||||||
};
|
};
|
||||||
|
|
||||||
// opakowanie modelu, określające stan egzemplarza
|
// opakowanie modelu, określające stan egzemplarza
|
||||||
class TAnimModel {
|
class TAnimModel : public editor::basic_node {
|
||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
TAnimModel( scene::node_data const &Nodedata );
|
||||||
|
TAnimModel();
|
||||||
|
// destructor
|
||||||
|
~TAnimModel();
|
||||||
|
// methods
|
||||||
|
static void AnimUpdate( double dt );
|
||||||
|
bool Init(TModel3d *pNewModel);
|
||||||
|
bool Init(std::string const &asName, std::string const &asReplacableTexture);
|
||||||
|
bool Load(cParser *parser, bool ter = false);
|
||||||
|
TAnimContainer * AddContainer(std::string const &Name);
|
||||||
|
TAnimContainer * GetContainer(std::string const &Name = "");
|
||||||
|
void RaAnglesSet( glm::vec3 Angles ) {
|
||||||
|
vAngle.x = Angles.x;
|
||||||
|
vAngle.y = Angles.y;
|
||||||
|
vAngle.z = Angles.z; };
|
||||||
|
void LightSet( int n, float v );
|
||||||
|
void AnimationVND( void *pData, double a, double b, double c, double d );
|
||||||
|
bool TerrainLoaded();
|
||||||
|
int TerrainCount();
|
||||||
|
TSubModel * TerrainSquare(int n);
|
||||||
|
int Flags();
|
||||||
|
inline
|
||||||
|
material_data const *
|
||||||
|
Material() const {
|
||||||
|
return &m_materialdata; }
|
||||||
|
inline
|
||||||
|
TModel3d *
|
||||||
|
Model() {
|
||||||
|
return pModel; }
|
||||||
|
// members
|
||||||
|
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// calculates piece's bounding radius
|
||||||
|
void
|
||||||
|
radius_();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TAnimContainer *pRoot; // pojemniki sterujące, tylko dla aniomowanych submodeli
|
// methods
|
||||||
TModel3d *pModel;
|
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
|
||||||
double fBlinkTimer;
|
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
|
||||||
int iNumLights;
|
void Advanced();
|
||||||
|
// members
|
||||||
|
TAnimContainer *pRoot { nullptr }; // pojemniki sterujące, tylko dla aniomowanych submodeli
|
||||||
|
TModel3d *pModel { nullptr };
|
||||||
|
double fBlinkTimer { 0.0 };
|
||||||
|
int iNumLights { 0 };
|
||||||
TSubModel *LightsOn[ iMaxNumLights ]; // Ra: te wskaźniki powinny być w ramach TModel3d
|
TSubModel *LightsOn[ iMaxNumLights ]; // Ra: te wskaźniki powinny być w ramach TModel3d
|
||||||
TSubModel *LightsOff[ iMaxNumLights ];
|
TSubModel *LightsOff[ iMaxNumLights ];
|
||||||
vector3 vAngle; // bazowe obroty egzemplarza względem osi
|
vector3 vAngle; // bazowe obroty egzemplarza względem osi
|
||||||
@@ -145,39 +179,17 @@ class TAnimModel {
|
|||||||
|
|
||||||
std::string asText; // tekst dla wyświetlacza znakowego
|
std::string asText; // tekst dla wyświetlacza znakowego
|
||||||
TAnimAdvanced *pAdvanced { nullptr };
|
TAnimAdvanced *pAdvanced { nullptr };
|
||||||
void Advanced();
|
|
||||||
TLightState lsLights[ iMaxNumLights ];
|
TLightState lsLights[ iMaxNumLights ];
|
||||||
float fDark; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
|
float fDark { DefaultDarkThresholdLevel }; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
|
||||||
float fOnTime, fOffTime; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza
|
float fOnTime { 0.66f };
|
||||||
|
float fOffTime { 0.66f + 0.66f }; // były stałymi, teraz mogą być zmienne dla każdego egzemplarza
|
||||||
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
||||||
private:
|
|
||||||
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
|
|
||||||
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
|
|
||||||
public:
|
|
||||||
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
|
||||||
inline
|
|
||||||
material_data const *Material() const { return &m_materialdata; }
|
|
||||||
|
|
||||||
TAnimModel();
|
|
||||||
~TAnimModel();
|
|
||||||
bool Init(TModel3d *pNewModel);
|
|
||||||
bool Init(std::string const &asName, std::string const &asReplacableTexture);
|
|
||||||
bool Load(cParser *parser, bool ter = false);
|
|
||||||
TAnimContainer * AddContainer(std::string const &Name);
|
|
||||||
TAnimContainer * GetContainer(std::string const &Name = "");
|
|
||||||
int Flags();
|
|
||||||
void RaAnglesSet(double a, double b, double c)
|
|
||||||
{
|
|
||||||
vAngle.x = a;
|
|
||||||
vAngle.y = b;
|
|
||||||
vAngle.z = c;
|
|
||||||
};
|
};
|
||||||
bool TerrainLoaded();
|
|
||||||
int TerrainCount();
|
|
||||||
TSubModel * TerrainSquare(int n);
|
|
||||||
void AnimationVND(void *pData, double a, double b, double c, double d);
|
class instance_table : public basic_table<TAnimModel> {
|
||||||
void LightSet(int n, float v);
|
|
||||||
static void AnimUpdate(double dt);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ set(SOURCES
|
|||||||
"Float3d.cpp"
|
"Float3d.cpp"
|
||||||
"Gauge.cpp"
|
"Gauge.cpp"
|
||||||
"Globals.cpp"
|
"Globals.cpp"
|
||||||
"Ground.cpp"
|
|
||||||
"Logs.cpp"
|
"Logs.cpp"
|
||||||
"McZapkie/friction.cpp"
|
"McZapkie/friction.cpp"
|
||||||
"McZapkie/hamulce.cpp"
|
"McZapkie/hamulce.cpp"
|
||||||
@@ -68,6 +67,11 @@ set(SOURCES
|
|||||||
"material.cpp"
|
"material.cpp"
|
||||||
"lua.cpp"
|
"lua.cpp"
|
||||||
"uart.cpp"
|
"uart.cpp"
|
||||||
|
"messaging.cpp"
|
||||||
|
"scene.cpp"
|
||||||
|
"scenenode.cpp"
|
||||||
|
"simulation.cpp"
|
||||||
|
"vertex.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// TViewPyramid TCamera::OrgViewPyramid;
|
|
||||||
//={vector3(-1,1,1),vector3(1,1,1),vector3(-1,-1,1),vector3(1,-1,1),vector3(0,0,0)};
|
|
||||||
|
|
||||||
void TCamera::Init(vector3 NPos, vector3 NAngle)
|
void TCamera::Init(vector3 NPos, vector3 NAngle)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -37,8 +34,8 @@ void TCamera::Init(vector3 NPos, vector3 NAngle)
|
|||||||
void TCamera::OnCursorMove(double x, double y)
|
void TCamera::OnCursorMove(double x, double y)
|
||||||
{
|
{
|
||||||
// McZapkie-170402: zeby mysz dzialala zawsze if (Type==tp_Follow)
|
// McZapkie-170402: zeby mysz dzialala zawsze if (Type==tp_Follow)
|
||||||
Pitch += y;
|
Yaw -= x;
|
||||||
Yaw += -x;
|
Pitch -= y;
|
||||||
if (Yaw > M_PI)
|
if (Yaw > M_PI)
|
||||||
Yaw -= 2 * M_PI;
|
Yaw -= 2 * M_PI;
|
||||||
else if (Yaw < -M_PI)
|
else if (Yaw < -M_PI)
|
||||||
@@ -62,7 +59,7 @@ TCamera::OnCommand( command_data const &Command ) {
|
|||||||
|
|
||||||
OnCursorMove(
|
OnCursorMove(
|
||||||
reinterpret_cast<double const &>( Command.param1 ) * 0.005 * Global::fMouseXScale / Global::ZoomFactor,
|
reinterpret_cast<double const &>( Command.param1 ) * 0.005 * Global::fMouseXScale / Global::ZoomFactor,
|
||||||
reinterpret_cast<double const &>( Command.param2 ) * -0.01 * Global::fMouseYScale / Global::ZoomFactor );
|
reinterpret_cast<double const &>( Command.param2 ) * 0.01 * Global::fMouseYScale / Global::ZoomFactor );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class TMtableTime; // czas dla danego posterunku
|
|||||||
|
|
||||||
class TController; // obiekt sterujący pociągiem (AI)
|
class TController; // obiekt sterujący pociągiem (AI)
|
||||||
|
|
||||||
typedef enum
|
enum TCommandType
|
||||||
{ // binarne odpowiedniki komend w komórce pamięci
|
{ // binarne odpowiedniki komend w komórce pamięci
|
||||||
cm_Unknown, // ciąg nierozpoznany (nie jest komendą)
|
cm_Unknown, // ciąg nierozpoznany (nie jest komendą)
|
||||||
cm_Ready, // W4 zezwala na odjazd, ale semafor może zatrzymać
|
cm_Ready, // W4 zezwala na odjazd, ale semafor może zatrzymać
|
||||||
@@ -51,6 +51,6 @@ typedef enum
|
|||||||
cm_OutsideStation,
|
cm_OutsideStation,
|
||||||
cm_Shunt,
|
cm_Shunt,
|
||||||
cm_Command // komenda pobierana z komórki
|
cm_Command // komenda pobierana z komórki
|
||||||
} TCommandType;
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
352
Driver.cpp
352
Driver.cpp
@@ -20,7 +20,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "mtable.h"
|
#include "mtable.h"
|
||||||
#include "DynObj.h"
|
#include "DynObj.h"
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "Ground.h"
|
|
||||||
#include "MemCell.h"
|
#include "MemCell.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "McZapkie/mctools.h"
|
#include "McZapkie/mctools.h"
|
||||||
@@ -73,8 +72,18 @@ double GetDistanceToEvent(TTrack const *track, TEvent const *event, double scan_
|
|||||||
{ // przejście na inny tor
|
{ // przejście na inny tor
|
||||||
track = track->Connected(int(sd), sd);
|
track = track->Connected(int(sd), sd);
|
||||||
start_dist += (1 == krok) ? 0 : back ? -segment->GetLength() : segment->GetLength();
|
start_dist += (1 == krok) ? 0 : back ? -segment->GetLength() : segment->GetLength();
|
||||||
|
if( ( track != nullptr )
|
||||||
|
&& ( track->eType == tt_Cross ) ) {
|
||||||
|
// NOTE: tracing through crossroads currently poses risk of tracing through wrong segment
|
||||||
|
// as it's possible to be performerd before setting a route through the crossroads
|
||||||
|
// as a stop-gap measure we don't trace through crossroads which should be reasonable in most cases
|
||||||
|
// TODO: establish route before the scan, or a way for the function to know which route to pick
|
||||||
|
return start_dist;
|
||||||
|
}
|
||||||
|
else {
|
||||||
return GetDistanceToEvent( track, event, sd, start_dist, ++iter, 1 == krok ? true : false );
|
return GetDistanceToEvent( track, event, sd, start_dist, ++iter, 1 == krok ? true : false );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{ // obliczenie mojego toru
|
{ // obliczenie mojego toru
|
||||||
seg_len -= scan_dir > 0 ? dzielnik : -dzielnik; //trzeba wrócić do pozycji len1
|
seg_len -= scan_dir > 0 ? dzielnik : -dzielnik; //trzeba wrócić do pozycji len1
|
||||||
@@ -303,7 +312,7 @@ bool TSpeedPos::Update()
|
|||||||
std::string TSpeedPos::GetName()
|
std::string TSpeedPos::GetName()
|
||||||
{
|
{
|
||||||
if (iFlags & spTrack) // jeśli tor
|
if (iFlags & spTrack) // jeśli tor
|
||||||
return trTrack->NameGet();
|
return trTrack->name();
|
||||||
else if( iFlags & spEvent ) // jeśli event
|
else if( iFlags & spEvent ) // jeśli event
|
||||||
return evEvent->asName;
|
return evEvent->asName;
|
||||||
else
|
else
|
||||||
@@ -517,7 +526,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
|||||||
if (pTrack != tLast) // ostatni zapisany w tabelce nie był jeszcze sprawdzony
|
if (pTrack != tLast) // ostatni zapisany w tabelce nie był jeszcze sprawdzony
|
||||||
{ // jeśli tor nie był jeszcze sprawdzany
|
{ // jeśli tor nie był jeszcze sprawdzany
|
||||||
if( Global::iWriteLogEnabled & 8 ) {
|
if( Global::iWriteLogEnabled & 8 ) {
|
||||||
WriteLog( "Speed table for " + OwnerName() + " tracing through track " + pTrack->NameGet() );
|
WriteLog( "Speed table for " + OwnerName() + " tracing through track " + pTrack->name() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( pEvent = CheckTrackEvent( pTrack, fLastDir ) ) != nullptr ) // jeśli jest semafor na tym torze
|
if( ( pEvent = CheckTrackEvent( pTrack, fLastDir ) ) != nullptr ) // jeśli jest semafor na tym torze
|
||||||
@@ -584,7 +593,11 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
|||||||
(fLastDir < 0 ?
|
(fLastDir < 0 ?
|
||||||
tLast->iPrevDirection :
|
tLast->iPrevDirection :
|
||||||
tLast->iNextDirection),
|
tLast->iNextDirection),
|
||||||
iRouteWanted) & 0xf) << 28); // ostatnie 4 bity pola flag
|
/*
|
||||||
|
iRouteWanted )
|
||||||
|
*/
|
||||||
|
1 + std::floor( Random( static_cast<double>(pTrack->RouteCount()) - 0.001 ) ) )
|
||||||
|
& 0xf ) << 28 ); // ostatnie 4 bity pola flag
|
||||||
sSpeedTable[iLast].iFlags &= ~spReverse; // usunięcie flagi kierunku, bo może być błędna
|
sSpeedTable[iLast].iFlags &= ~spReverse; // usunięcie flagi kierunku, bo może być błędna
|
||||||
if (sSpeedTable[iLast].iFlags < 0) {
|
if (sSpeedTable[iLast].iFlags < 0) {
|
||||||
sSpeedTable[iLast].iFlags |= spReverse; // ustawienie flagi kierunku na podstawie wybranego segmentu
|
sSpeedTable[iLast].iFlags |= spReverse; // ustawienie flagi kierunku na podstawie wybranego segmentu
|
||||||
@@ -592,10 +605,12 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
|||||||
if (int(fLastDir) * sSpeedTable[iLast].iFlags < 0) {
|
if (int(fLastDir) * sSpeedTable[iLast].iFlags < 0) {
|
||||||
fLastDir = -fLastDir;
|
fLastDir = -fLastDir;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (AIControllFlag) {
|
if (AIControllFlag) {
|
||||||
// dla AI na razie losujemy kierunek na kolejnym skrzyżowaniu
|
// dla AI na razie losujemy kierunek na kolejnym skrzyżowaniu
|
||||||
iRouteWanted = 1 + Random(3);
|
iRouteWanted = 1 + Random(3);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ( pTrack->fRadius != 0.0 ) // odległość na łuku lepiej aproksymować cięciwami
|
else if ( ( pTrack->fRadius != 0.0 ) // odległość na łuku lepiej aproksymować cięciwami
|
||||||
@@ -708,7 +723,7 @@ void TController::TableCheck(double fDistance)
|
|||||||
if (sSpeedTable[i].Update())
|
if (sSpeedTable[i].Update())
|
||||||
{
|
{
|
||||||
if( Global::iWriteLogEnabled & 8 ) {
|
if( Global::iWriteLogEnabled & 8 ) {
|
||||||
WriteLog( "Speed table for " + OwnerName() + " detected switch change at " + sSpeedTable[ i ].trTrack->NameGet() + " (generating fresh trace)" );
|
WriteLog( "Speed table for " + OwnerName() + " detected switch change at " + sSpeedTable[ i ].trTrack->name() + " (generating fresh trace)" );
|
||||||
}
|
}
|
||||||
// usuwamy wszystko za tym torem
|
// usuwamy wszystko za tym torem
|
||||||
while (sSpeedTable.back().trTrack != sSpeedTable[i].trTrack)
|
while (sSpeedTable.back().trTrack != sSpeedTable[i].trTrack)
|
||||||
@@ -812,7 +827,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
WriteLog(
|
WriteLog(
|
||||||
pVehicle->asName + " as " + TrainParams->TrainName
|
pVehicle->asName + " as " + TrainParams->TrainName
|
||||||
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
|
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
|
||||||
+ " skipped " + asNextStop); // informacja
|
+ " passed " + asNextStop); // informacja
|
||||||
#endif
|
#endif
|
||||||
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
|
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
|
||||||
fLastStopExpDist = mvOccupied->DistCounter + 0.250 + 0.001 * fLength;
|
fLastStopExpDist = mvOccupied->DistCounter + 0.250 + 0.001 * fLength;
|
||||||
@@ -1252,7 +1267,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
// jeśli ma stać, dostaje komendę od razu
|
// jeśli ma stać, dostaje komendę od razu
|
||||||
go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
|
go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
|
||||||
}
|
}
|
||||||
else if( sSpeedTable[ i ].fDist <= 20.0 ) {
|
else if( sSpeedTable[ i ].fDist <= fMaxProximityDist ) {
|
||||||
// jeśli ma dociągnąć, to niech dociąga
|
// jeśli ma dociągnąć, to niech dociąga
|
||||||
// (moveStopCloser dotyczy dociągania do W4, nie semafora)
|
// (moveStopCloser dotyczy dociągania do W4, nie semafora)
|
||||||
go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
|
go = cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
|
||||||
@@ -1782,7 +1797,7 @@ void TController::AutoRewident()
|
|||||||
}
|
}
|
||||||
if (mvOccupied->TrainType == dt_EZT)
|
if (mvOccupied->TrainType == dt_EZT)
|
||||||
{
|
{
|
||||||
fAccThreshold = -fBrake_a0[BrakeAccTableSize] - 8 * fBrake_a1[BrakeAccTableSize];
|
fAccThreshold = std::max(-fBrake_a0[BrakeAccTableSize] - 8 * fBrake_a1[BrakeAccTableSize], -0.75);
|
||||||
fBrakeReaction = 0.25;
|
fBrakeReaction = 0.25;
|
||||||
}
|
}
|
||||||
else if (ustaw > 16)
|
else if (ustaw > 16)
|
||||||
@@ -2415,9 +2430,24 @@ bool TController::IncBrake()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
/*
|
||||||
standalone =
|
standalone =
|
||||||
( ( mvOccupied->Couplers[ 0 ].CouplingFlag == 0 )
|
( ( mvOccupied->Couplers[ 0 ].CouplingFlag == 0 )
|
||||||
&& ( mvOccupied->Couplers[ 1 ].CouplingFlag == 0 ) );
|
&& ( mvOccupied->Couplers[ 1 ].CouplingFlag == 0 ) );
|
||||||
|
*/
|
||||||
|
if( pVehicles[ 0 ] != pVehicles[ 1 ] ) {
|
||||||
|
// more detailed version, will use manual braking also for coupled sets of controlled vehicles
|
||||||
|
auto *vehicle = pVehicles[ 0 ]; // start from first
|
||||||
|
while( ( true == standalone )
|
||||||
|
&& ( vehicle != nullptr ) ) {
|
||||||
|
// NOTE: we could simplify this by doing only check of the rear coupler, but this can be quite tricky in itself
|
||||||
|
// TODO: add easier ways to access front/rear coupler taking into account vehicle's direction
|
||||||
|
standalone =
|
||||||
|
( ( ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 0 ].CouplingFlag & coupling::control ) )
|
||||||
|
&& ( ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag == 0 ) || ( vehicle->MoverParameters->Couplers[ 1 ].CouplingFlag & coupling::control ) ) );
|
||||||
|
vehicle = vehicle->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( true == standalone ) {
|
if( true == standalone ) {
|
||||||
OK = mvOccupied->IncLocalBrakeLevel(
|
OK = mvOccupied->IncLocalBrakeLevel(
|
||||||
@@ -2973,20 +3003,15 @@ void TController::RecognizeCommand()
|
|||||||
c->Command = ""; // usunięcie obsłużonej komendy
|
c->Command = ""; // usunięcie obsłużonej komendy
|
||||||
}
|
}
|
||||||
|
|
||||||
void TController::PutCommand(std::string NewCommand, double NewValue1, double NewValue2,
|
void TController::PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation, TStopReason reason)
|
||||||
const TLocation &NewLocation, TStopReason reason)
|
{ // wysłanie komendy przez event PutValues, jak pojazd ma obsadę, to wysyła tutaj, a nie do pojazdu bezpośrednio
|
||||||
{ // wysłanie komendy przez event PutValues, jak pojazd ma obsadę, to wysyła tutaj, a nie do pojazdu
|
// zamiana na współrzędne scenerii
|
||||||
// bezpośrednio
|
glm::dvec3 sl { -NewLocation.X, NewLocation.Z, NewLocation.Y };
|
||||||
vector3 sl;
|
|
||||||
sl.x = -NewLocation.X; // zamiana na współrzędne scenerii
|
|
||||||
sl.z = NewLocation.Y;
|
|
||||||
sl.y = NewLocation.Z;
|
|
||||||
if (!PutCommand(NewCommand, NewValue1, NewValue2, &sl, reason))
|
if (!PutCommand(NewCommand, NewValue1, NewValue2, &sl, reason))
|
||||||
mvOccupied->PutCommand(NewCommand, NewValue1, NewValue2, NewLocation);
|
mvOccupied->PutCommand(NewCommand, NewValue1, NewValue2, NewLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TController::PutCommand(std::string NewCommand, double NewValue1, double NewValue2,
|
bool TController::PutCommand( std::string NewCommand, double NewValue1, double NewValue2, glm::dvec3 const *NewLocation, TStopReason reason )
|
||||||
const vector3 *NewLocation, TStopReason reason)
|
|
||||||
{ // analiza komendy
|
{ // analiza komendy
|
||||||
if (NewCommand == "CabSignal")
|
if (NewCommand == "CabSignal")
|
||||||
{ // SHP wyzwalane jest przez człon z obsadą, ale obsługiwane przez silnikowy
|
{ // SHP wyzwalane jest przez człon z obsadą, ale obsługiwane przez silnikowy
|
||||||
@@ -3639,6 +3664,14 @@ TController::UpdateSituation(double dt) {
|
|||||||
// dla nastawienia G koniecznie należy wydłużyć drogę na czas reakcji
|
// dla nastawienia G koniecznie należy wydłużyć drogę na czas reakcji
|
||||||
fBrakeDist += 2 * mvOccupied->Vel;
|
fBrakeDist += 2 * mvOccupied->Vel;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
// take into account effect of gravity (but to stay on safe side of calculations, only downhill)
|
||||||
|
if( fAccGravity > 0.025 ) {
|
||||||
|
fBrakeDist *= ( 1.0 + fAccGravity );
|
||||||
|
// TBD: use version which shortens route going uphill, too
|
||||||
|
//fBrakeDist = std::max( fBrakeDist, fBrakeDist * ( 1.0 + fAccGravity ) );
|
||||||
|
}
|
||||||
|
*/
|
||||||
// route scan
|
// route scan
|
||||||
double routescanrange = (
|
double routescanrange = (
|
||||||
mvOccupied->Vel > 5.0 ?
|
mvOccupied->Vel > 5.0 ?
|
||||||
@@ -3812,8 +3845,11 @@ TController::UpdateSituation(double dt) {
|
|||||||
CheckVehicles(); // sprawdzić światła nowego składu
|
CheckVehicles(); // sprawdzić światła nowego składu
|
||||||
JumpToNextOrder(); // wykonanie następnej komendy
|
JumpToNextOrder(); // wykonanie następnej komendy
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
// NOTE: disabled as speed limit is decided in another place based on distance to potential target
|
||||||
else
|
else
|
||||||
SetVelocity(2.0, 0.0); // jazda w ustawionym kierunku z prędkością 2 (18s)
|
SetVelocity(2.0, 0.0); // jazda w ustawionym kierunku z prędkością 2 (18s)
|
||||||
|
*/
|
||||||
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
|
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -4208,13 +4244,12 @@ TController::UpdateSituation(double dt) {
|
|||||||
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders
|
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders
|
||||||
if (fabs(VelSignal) >=
|
if (fabs(VelSignal) >=
|
||||||
1.0) // 0.1 nie wysyła się do samochodow, bo potem nie ruszą
|
1.0) // 0.1 nie wysyła się do samochodow, bo potem nie ruszą
|
||||||
PutCommand("SetVelocity", VelSignal, VelNext,
|
PutCommand("SetVelocity", VelSignal, VelNext, nullptr); // komenda robi dodatkowe operacje
|
||||||
NULL); // komenda robi dodatkowe operacje
|
|
||||||
break;
|
break;
|
||||||
case cm_ShuntVelocity: // od wersji 357 Tm nie budzi wyłączonej lokomotywy
|
case cm_ShuntVelocity: // od wersji 357 Tm nie budzi wyłączonej lokomotywy
|
||||||
if (!(OrderList[OrderPos] &
|
if (!(OrderList[OrderPos] &
|
||||||
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders
|
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders
|
||||||
PutCommand("ShuntVelocity", VelSignal, VelNext, NULL);
|
PutCommand("ShuntVelocity", VelSignal, VelNext, nullptr);
|
||||||
else if (iCoupler) // jeśli jedzie w celu połączenia
|
else if (iCoupler) // jeśli jedzie w celu połączenia
|
||||||
SetVelocity(VelSignal, VelNext);
|
SetVelocity(VelSignal, VelNext);
|
||||||
break;
|
break;
|
||||||
@@ -4302,7 +4337,12 @@ TController::UpdateSituation(double dt) {
|
|||||||
if( OrderCurrentGet() & Connect ) {
|
if( OrderCurrentGet() & Connect ) {
|
||||||
// jeśli spinanie, to jechać dalej
|
// jeśli spinanie, to jechać dalej
|
||||||
AccPreferred = std::min( 0.25, AccPreferred ); // nie hamuj
|
AccPreferred = std::min( 0.25, AccPreferred ); // nie hamuj
|
||||||
VelDesired = Global::Min0RSpeed( 20.0, VelDesired );
|
VelDesired =
|
||||||
|
Global::Min0RSpeed(
|
||||||
|
VelDesired,
|
||||||
|
( vehicle->fTrackBlock > 150.0 ?
|
||||||
|
20.0:
|
||||||
|
4.0 ) );
|
||||||
VelNext = 2.0; // i pakuj się na tamtego
|
VelNext = 2.0; // i pakuj się na tamtego
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -4345,7 +4385,12 @@ TController::UpdateSituation(double dt) {
|
|||||||
else {
|
else {
|
||||||
if( OrderCurrentGet() & Connect ) {
|
if( OrderCurrentGet() & Connect ) {
|
||||||
// if there's something nearby in the connect mode don't speed up too much
|
// if there's something nearby in the connect mode don't speed up too much
|
||||||
VelDesired = Global::Min0RSpeed( 20.0, VelDesired );
|
VelDesired =
|
||||||
|
Global::Min0RSpeed(
|
||||||
|
VelDesired,
|
||||||
|
( vehicle->fTrackBlock > 150.0 ?
|
||||||
|
20.0 :
|
||||||
|
4.0 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4452,6 +4497,7 @@ TController::UpdateSituation(double dt) {
|
|||||||
AbsAccS /= fMass;
|
AbsAccS /= fMass;
|
||||||
}
|
}
|
||||||
AbsAccS_pub = AbsAccS;
|
AbsAccS_pub = AbsAccS;
|
||||||
|
AbsAccS_avg = interpolate( AbsAccS_avg, mvOccupied->AccS * iDirection, 0.25 );
|
||||||
|
|
||||||
#if LOGVELOCITY
|
#if LOGVELOCITY
|
||||||
// WriteLog("VelDesired="+AnsiString(VelDesired)+",
|
// WriteLog("VelDesired="+AnsiString(VelDesired)+",
|
||||||
@@ -4580,8 +4626,34 @@ TController::UpdateSituation(double dt) {
|
|||||||
|
|
||||||
// decisions based on current speed
|
// decisions based on current speed
|
||||||
if( mvOccupied->CategoryFlag == 1 ) {
|
if( mvOccupied->CategoryFlag == 1 ) {
|
||||||
|
|
||||||
|
if( fAccGravity < 0.025 ) {
|
||||||
|
// on flats on uphill we can be less careful
|
||||||
|
if( vel > VelDesired ) {
|
||||||
|
// jesli jedzie za szybko do AKTUALNEGO
|
||||||
|
if( VelDesired == 0.0 ) {
|
||||||
|
// jesli stoj, to hamuj, ale i tak juz za pozno :)
|
||||||
|
AccDesired = std::min( AccDesired, -0.85 ); // hamuj solidnie
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// slow down, not full stop
|
||||||
|
if( vel > ( VelDesired + fVelPlus ) ) {
|
||||||
|
// hamuj tak średnio
|
||||||
|
AccDesired = std::min( AccDesired, -0.25 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// o 5 km/h to olej (zacznij luzować)
|
||||||
|
AccDesired = std::min(
|
||||||
|
AccDesired, // but don't override decceleration for VelNext
|
||||||
|
std::max( 0.0, AccPreferred ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// going sharply downhill we may need to start braking sooner than usual
|
||||||
// try to estimate increase of current velocity before engaged brakes start working
|
// try to estimate increase of current velocity before engaged brakes start working
|
||||||
auto const speedestimate = vel + vel * ( 1.0 - fBrake_a0[ 0 ] ) * AbsAccS;
|
auto const speedestimate = vel + ( 1.0 - fBrake_a0[ 0 ] ) * 30.0 * AbsAccS;
|
||||||
if( speedestimate > VelDesired ) {
|
if( speedestimate > VelDesired ) {
|
||||||
// jesli jedzie za szybko do AKTUALNEGO
|
// jesli jedzie za szybko do AKTUALNEGO
|
||||||
if( VelDesired == 0.0 ) {
|
if( VelDesired == 0.0 ) {
|
||||||
@@ -4604,6 +4676,7 @@ TController::UpdateSituation(double dt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// for cars the older version works better
|
// for cars the older version works better
|
||||||
if( vel > VelDesired ) {
|
if( vel > VelDesired ) {
|
||||||
@@ -4631,8 +4704,10 @@ TController::UpdateSituation(double dt) {
|
|||||||
|
|
||||||
// last step sanity check, until the whole calculation is straightened out
|
// last step sanity check, until the whole calculation is straightened out
|
||||||
AccDesired = std::min( AccDesired, AccPreferred );
|
AccDesired = std::min( AccDesired, AccPreferred );
|
||||||
if( mvOccupied->CategoryFlag == 1 ) {
|
|
||||||
// also take into account impact of gravity
|
if( ( mvOccupied->CategoryFlag == 1 )
|
||||||
|
&& ( fAccGravity > 0.025 ) ) {
|
||||||
|
// going downhill also take into account impact of gravity
|
||||||
AccDesired = clamp( AccDesired - fAccGravity, -0.9, 0.9 );
|
AccDesired = clamp( AccDesired - fAccGravity, -0.9, 0.9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4884,41 +4959,19 @@ TController::UpdateSituation(double dt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Mietek-end1
|
if ((AccDesired < fAccGravity - 0.05) && (AbsAccS < AccDesired - fBrake_a1[0]*0.51)) {
|
||||||
SpeedSet(); // ciągla regulacja prędkości
|
// jak hamuje, to nie tykaj kranu za często
|
||||||
#if LOGVELOCITY
|
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
|
||||||
WriteLog("BrakePos=" + AnsiString(mvOccupied->BrakeCtrlPos) + ", MainCtrl=" +
|
if( OrderList[ OrderPos ] != Disconnect ) {
|
||||||
AnsiString(mvControlling->MainCtrlPos));
|
// przy odłączaniu nie zwalniamy tu hamulca
|
||||||
#endif
|
DecBrake(); // tutaj zmniejszało o 1 przy odczepianiu
|
||||||
|
|
||||||
/* //Ra: mamy teraz wskażnik na człon silnikowy, gorzej jak są dwa w
|
|
||||||
ukrotnieniu...
|
|
||||||
//zapobieganie poslizgowi w czlonie silnikowym; Ra: Couplers[1] powinno
|
|
||||||
być
|
|
||||||
if (Controlling->Couplers[0].Connected!=NULL)
|
|
||||||
if (TestFlag(Controlling->Couplers[0].CouplingFlag,ctrain_controll))
|
|
||||||
if (Controlling->Couplers[0].Connected->SlippingWheels)
|
|
||||||
if (Controlling->ScndCtrlPos>0?!Controlling->DecScndCtrl(1):true)
|
|
||||||
{
|
|
||||||
if (!Controlling->DecMainCtrl(1))
|
|
||||||
if (mvOccupied->BrakeCtrlPos==mvOccupied->BrakeCtrlPosNo)
|
|
||||||
mvOccupied->DecBrakeLevel();
|
|
||||||
++iDriverFailCount;
|
|
||||||
}
|
}
|
||||||
*/
|
fBrakeTime = (
|
||||||
// zapobieganie poslizgowi u nas
|
mvOccupied->BrakeDelayFlag > bdelay_G ?
|
||||||
if (mvControlling->SlippingWheels)
|
mvOccupied->BrakeDelay[ 0 ] :
|
||||||
{
|
mvOccupied->BrakeDelay[ 2 ] )
|
||||||
if (!mvControlling->DecScndCtrl(2)) // bocznik na zero
|
/ 3.0;
|
||||||
mvControlling->DecMainCtrl(1);
|
fBrakeTime *= 0.5; // Ra: tymczasowo, bo przeżyna S1
|
||||||
if (mvOccupied->BrakeCtrlPos ==
|
|
||||||
mvOccupied->BrakeCtrlPosNo) // jeśli ostatnia pozycja hamowania
|
|
||||||
//yB: ten warunek wyżej nie ma sensu
|
|
||||||
mvOccupied->DecBrakeLevel(); // to cofnij hamulec
|
|
||||||
else
|
|
||||||
mvControlling->AntiSlippingButton();
|
|
||||||
++iDriverFailCount;
|
|
||||||
//mvControlling->SlippingWheels = false; // flaga już wykorzystana
|
|
||||||
}
|
}
|
||||||
// stop-gap measure to ensure cars actually brake to stop even when above calculactions go awry
|
// stop-gap measure to ensure cars actually brake to stop even when above calculactions go awry
|
||||||
// instead of releasing the brakes and creeping into obstacle at 1-2 km/h
|
// instead of releasing the brakes and creeping into obstacle at 1-2 km/h
|
||||||
@@ -5177,7 +5230,7 @@ std::string TController::StopReasonText()
|
|||||||
if (eStopReason != 7) // zawalidroga będzie inaczej
|
if (eStopReason != 7) // zawalidroga będzie inaczej
|
||||||
return StopReasonTable[eStopReason];
|
return StopReasonTable[eStopReason];
|
||||||
else
|
else
|
||||||
return "Blocked by " + (pVehicles[0]->PrevAny()->GetName());
|
return "Blocked by " + (pVehicles[0]->PrevAny()->name());
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -5280,7 +5333,7 @@ TTrack * TController::BackwardTraceRoute(double &fDistance, double &fDirection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sprawdzanie zdarzeń semaforów i ograniczeń szlakowych
|
// sprawdzanie zdarzeń semaforów i ograniczeń szlakowych
|
||||||
void TController::SetProximityVelocity(double dist, double vel, const vector3 *pos)
|
void TController::SetProximityVelocity( double dist, double vel, glm::dvec3 const *pos )
|
||||||
{ // Ra:przeslanie do AI prędkości
|
{ // Ra:przeslanie do AI prędkości
|
||||||
/*
|
/*
|
||||||
//!!!! zastąpić prawidłową reakcją AI na SetProximityVelocity !!!!
|
//!!!! zastąpić prawidłową reakcją AI na SetProximityVelocity !!!!
|
||||||
@@ -5304,43 +5357,47 @@ void TController::SetProximityVelocity(double dist, double vel, const vector3 *p
|
|||||||
|
|
||||||
TCommandType TController::BackwardScan()
|
TCommandType TController::BackwardScan()
|
||||||
{ // sprawdzanie zdarzeń semaforów z tyłu pojazdu, zwraca komendę
|
{ // sprawdzanie zdarzeń semaforów z tyłu pojazdu, zwraca komendę
|
||||||
// dzięki temu będzie można stawać za wskazanym sygnalizatorem, a zwłaszcza jeśli będzie jazda
|
// dzięki temu będzie można stawać za wskazanym sygnalizatorem, a zwłaszcza jeśli będzie jazda na kozioł
|
||||||
// na kozioł
|
// ograniczenia prędkości nie są wtedy istotne, również koniec toru jest do niczego nie przydatny
|
||||||
// ograniczenia prędkości nie są wtedy istotne, również koniec toru jest do niczego nie
|
|
||||||
// przydatny
|
|
||||||
// zwraca true, jeśli należy odwrócić kierunek jazdy pojazdu
|
// zwraca true, jeśli należy odwrócić kierunek jazdy pojazdu
|
||||||
if ((OrderList[OrderPos] & ~(Shunt | Connect)))
|
if( ( OrderList[ OrderPos ] & ~( Shunt | Connect ) ) ) {
|
||||||
return cm_Unknown; // skanowanie sygnałów tylko gdy jedzie w trybie manewrowym albo czeka na
|
// skanowanie sygnałów tylko gdy jedzie w trybie manewrowym albo czeka na rozkazy
|
||||||
// rozkazy
|
return cm_Unknown;
|
||||||
|
}
|
||||||
vector3 sl;
|
vector3 sl;
|
||||||
int startdir =
|
// kierunek jazdy względem sprzęgów pojazdu na czele
|
||||||
-pVehicles[0]->DirectionGet(); // kierunek jazdy względem sprzęgów pojazdu na czele
|
int const startdir = -pVehicles[0]->DirectionGet();
|
||||||
if (startdir == 0) // jeśli kabina i kierunek nie jest określony
|
if( startdir == 0 ) {
|
||||||
return cm_Unknown; // nie robimy nic
|
// jeśli kabina i kierunek nie jest określony nie robimy nic
|
||||||
double scandir =
|
return cm_Unknown;
|
||||||
startdir * pVehicles[0]->RaDirectionGet(); // szukamy od pierwszej osi w wybranym kierunku
|
}
|
||||||
if (scandir !=
|
// szukamy od pierwszej osi w wybranym kierunku
|
||||||
0.0) // skanowanie toru w poszukiwaniu eventów GetValues (PutValues nie są przydatne)
|
double scandir = startdir * pVehicles[0]->RaDirectionGet();
|
||||||
{ // Ra: przy wstecznym skanowaniu prędkość nie ma znaczenia
|
if (scandir != 0.0) {
|
||||||
// scanback=pVehicles[1]->NextDistance(fLength+1000.0); //odległość do następnego pojazdu,
|
// skanowanie toru w poszukiwaniu eventów GetValues (PutValues nie są przydatne)
|
||||||
// 1000 gdy nic nie ma
|
// Ra: przy wstecznym skanowaniu prędkość nie ma znaczenia
|
||||||
double scanmax = 1000; // 1000m do tyłu, żeby widział przeciwny koniec stacji
|
double scanmax = 1000; // 1000m do tyłu, żeby widział przeciwny koniec stacji
|
||||||
double scandist = scanmax; // zmodyfikuje na rzeczywiście przeskanowane
|
double scandist = scanmax; // zmodyfikuje na rzeczywiście przeskanowane
|
||||||
TEvent *e = NULL; // event potencjalnie od semafora
|
TEvent *e = NULL; // event potencjalnie od semafora
|
||||||
// opcjonalnie może być skanowanie od "wskaźnika" z przodu, np. W5, Tm=Ms1, koniec toru
|
// opcjonalnie może być skanowanie od "wskaźnika" z przodu, np. W5, Tm=Ms1, koniec toru wg drugiej osi w kierunku ruchu
|
||||||
TTrack *scantrack = BackwardTraceRoute(scandist, scandir, pVehicles[0]->RaTrackGet(),
|
TTrack *scantrack = BackwardTraceRoute(scandist, scandir, pVehicles[0]->RaTrackGet(), e);
|
||||||
e); // wg drugiej osi w kierunku ruchu
|
vector3 const dir = startdir * pVehicles[0]->VectorFront(); // wektor w kierunku jazdy/szukania
|
||||||
vector3 dir = startdir * pVehicles[0]->VectorFront(); // wektor w kierunku jazdy/szukania
|
if( !scantrack ) {
|
||||||
if (!scantrack) // jeśli wstecz wykryto koniec toru
|
// jeśli wstecz wykryto koniec toru to raczej nic się nie da w takiej sytuacji zrobić
|
||||||
return cm_Unknown; // to raczej nic się nie da w takiej sytuacji zrobić
|
return cm_Unknown;
|
||||||
else
|
}
|
||||||
{ // a jeśli są dalej tory
|
else {
|
||||||
|
// a jeśli są dalej tory
|
||||||
double vmechmax; // prędkość ustawiona semaforem
|
double vmechmax; // prędkość ustawiona semaforem
|
||||||
if (e)
|
if( e != nullptr ) {
|
||||||
{ // jeśli jest jakiś sygnał na widoku
|
// jeśli jest jakiś sygnał na widoku
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
AnsiString edir =
|
std::string edir {
|
||||||
pVehicle->asName + " - " + AnsiString((scandir > 0) ? "Event2 " : "Event1 ");
|
"Backward scan by "
|
||||||
|
+ pVehicle->asName + " - "
|
||||||
|
+ ( ( scandir > 0 ) ?
|
||||||
|
"Event2 " :
|
||||||
|
"Event1 " ) };
|
||||||
#endif
|
#endif
|
||||||
// najpierw sprawdzamy, czy semafor czy inny znak został przejechany
|
// najpierw sprawdzamy, czy semafor czy inny znak został przejechany
|
||||||
vector3 pos = pVehicles[1]->RearPosition(); // pozycja tyłu
|
vector3 pos = pVehicles[1]->RearPosition(); // pozycja tyłu
|
||||||
@@ -5348,64 +5405,65 @@ TCommandType TController::BackwardScan()
|
|||||||
if (e->Type == tp_GetValues)
|
if (e->Type == tp_GetValues)
|
||||||
{ // przesłać info o zbliżającym się semaforze
|
{ // przesłać info o zbliżającym się semaforze
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
edir += "(" + (e->Params[8].asGroundNode->asName) + "): ";
|
edir += "(" + ( e->asNodeName ) + ")";
|
||||||
#endif
|
#endif
|
||||||
sl = e->PositionGet(); // położenie komórki pamięci
|
sl = e->PositionGet(); // położenie komórki pamięci
|
||||||
sem = sl - pos; // wektor do komórki pamięci od końca składu
|
sem = sl - pos; // wektor do komórki pamięci od końca składu
|
||||||
// sem=e->Params[8].asGroundNode->pCenter-pos; //wektor do komórki pamięci
|
if (dir.x * sem.x + dir.z * sem.z < 0) {
|
||||||
if (dir.x * sem.x + dir.z * sem.z < 0) // jeśli został minięty
|
// jeśli został minięty
|
||||||
// if ((mvOccupied->CategoryFlag&1)?(VelNext!=0.0):true) //dla pociągu wymagany
|
// iloczyn skalarny jest ujemny, gdy sygnał stoi z tyłu
|
||||||
// sygnał zezwalający
|
|
||||||
{ // iloczyn skalarny jest ujemny, gdy sygnał stoi z tyłu
|
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
WriteLog(edir + " - ignored as not passed yet");
|
WriteLog(edir + " - ignored as not passed yet");
|
||||||
#endif
|
#endif
|
||||||
return cm_Unknown; // nic
|
return cm_Unknown; // nic
|
||||||
}
|
}
|
||||||
vmechmax = e->ValueGet(1); // prędkość przy tym semaforze
|
vmechmax = e->ValueGet(1); // prędkość przy tym semaforze
|
||||||
// przeliczamy odległość od semafora - potrzebne by były współrzędne początku
|
// przeliczamy odległość od semafora - potrzebne by były współrzędne początku składu
|
||||||
// składu
|
|
||||||
// scandist=(pos-e->Params[8].asGroundNode->pCenter).Length()-0.5*mvOccupied->Dim.L-10;
|
|
||||||
// //10m luzu
|
|
||||||
scandist = sem.Length() - 2; // 2m luzu przy manewrach wystarczy
|
scandist = sem.Length() - 2; // 2m luzu przy manewrach wystarczy
|
||||||
if (scandist < 0)
|
if( scandist < 0 ) {
|
||||||
scandist = 0; // ujemnych nie ma po co wysyłać
|
// ujemnych nie ma po co wysyłać
|
||||||
|
scandist = 0;
|
||||||
|
}
|
||||||
bool move = false; // czy AI w trybie manewerowym ma dociągnąć pod S1
|
bool move = false; // czy AI w trybie manewerowym ma dociągnąć pod S1
|
||||||
if (e->Command() == cm_SetVelocity)
|
if( e->Command() == cm_SetVelocity ) {
|
||||||
if ((vmechmax == 0.0) ? (OrderCurrentGet() & (Shunt | Connect)) :
|
if( ( vmechmax == 0.0 ) ?
|
||||||
(OrderCurrentGet() &
|
( OrderCurrentGet() & ( Shunt | Connect ) ) :
|
||||||
Connect)) // przy podczepianiu ignorować wyjazd?
|
( OrderCurrentGet() & Connect ) ) { // przy podczepianiu ignorować wyjazd?
|
||||||
move = true; // AI w trybie manewerowym ma dociągnąć pod S1
|
move = true; // AI w trybie manewerowym ma dociągnąć pod S1
|
||||||
else
|
}
|
||||||
{ //
|
else {
|
||||||
if ((scandist > fMinProximityDist) ?
|
if( ( scandist > fMinProximityDist )
|
||||||
(mvOccupied->Vel > 0.0) && (OrderCurrentGet() != Shunt) :
|
&& ( ( mvOccupied->Vel > 0.0 )
|
||||||
false)
|
&& ( OrderCurrentGet() != Shunt ) ) ) {
|
||||||
{ // jeśli semafor jest daleko, a pojazd jedzie, to informujemy o
|
// jeśli semafor jest daleko, a pojazd jedzie, to informujemy o zmianie prędkości
|
||||||
// zmianie prędkości
|
|
||||||
// jeśli jedzie manewrowo, musi dostać SetVelocity, żeby sie na pociągowy przełączył
|
// jeśli jedzie manewrowo, musi dostać SetVelocity, żeby sie na pociągowy przełączył
|
||||||
// Mechanik->PutCommand("SetProximityVelocity",scandist,vmechmax,sl);
|
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
// WriteLog(edir+"SetProximityVelocity "+AnsiString(scandist)+"
|
// WriteLog(edir+"SetProximityVelocity "+AnsiString(scandist) + AnsiString(vmechmax));
|
||||||
// "+AnsiString(vmechmax));
|
|
||||||
WriteLog(edir);
|
WriteLog(edir);
|
||||||
#endif
|
#endif
|
||||||
// SetProximityVelocity(scandist,vmechmax,&sl);
|
// SetProximityVelocity(scandist,vmechmax,&sl);
|
||||||
return (vmechmax > 0) ? cm_SetVelocity : cm_Unknown;
|
return (
|
||||||
|
vmechmax > 0 ?
|
||||||
|
cm_SetVelocity :
|
||||||
|
cm_Unknown );
|
||||||
}
|
}
|
||||||
else // ustawiamy prędkość tylko wtedy, gdy ma ruszyć, stanąć albo ma
|
else {
|
||||||
// stać
|
// ustawiamy prędkość tylko wtedy, gdy ma ruszyć, stanąć albo ma stać
|
||||||
// if ((MoverParameters->Vel==0.0)||(vmechmax==0.0)) //jeśli stoi lub ma
|
// if ((MoverParameters->Vel==0.0)||(vmechmax==0.0)) //jeśli stoi lub ma stanąć/stać
|
||||||
// stanąć/stać
|
// semafor na tym torze albo lokomtywa stoi, a ma ruszyć, albo ma stanąć, albo nie ruszać
|
||||||
{ // semafor na tym torze albo lokomtywa stoi, a ma ruszyć, albo ma
|
|
||||||
// stanąć, albo nie ruszać
|
|
||||||
// stop trzeba powtarzać, bo inaczej zatrąbi i pojedzie sam
|
// stop trzeba powtarzać, bo inaczej zatrąbi i pojedzie sam
|
||||||
// PutCommand("SetVelocity",vmechmax,e->Params[9].asMemCell->Value2(),&sl,stopSem);
|
// PutCommand("SetVelocity",vmechmax,e->Params[9].asMemCell->Value2(),&sl,stopSem);
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
WriteLog(edir + "SetVelocity " + AnsiString(vmechmax) + " " +
|
WriteLog(
|
||||||
AnsiString(e->Params[9].asMemCell->Value2()));
|
edir + " - [SetVelocity] ["
|
||||||
|
+ to_string( vmechmax, 2 ) + "] ["
|
||||||
|
+ to_string( e->Params[ 9 ].asMemCell->Value2(), 2 ) + "]" );
|
||||||
#endif
|
#endif
|
||||||
return (vmechmax > 0) ? cm_SetVelocity : cm_Unknown;
|
return (
|
||||||
|
vmechmax > 0 ?
|
||||||
|
cm_SetVelocity :
|
||||||
|
cm_Unknown );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OrderCurrentGet() ? OrderCurrentGet() & (Shunt | Connect) :
|
if (OrderCurrentGet() ? OrderCurrentGet() & (Shunt | Connect) :
|
||||||
@@ -5434,28 +5492,34 @@ TCommandType TController::BackwardScan()
|
|||||||
// to można zmienić kierunek
|
// to można zmienić kierunek
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // ustawiamy prędkość tylko wtedy, gdy ma ruszyć, albo stanąć albo
|
else {
|
||||||
// ma stać pod tarczą
|
// ustawiamy prędkość tylko wtedy, gdy ma ruszyć, albo stanąć albo ma stać pod tarczą
|
||||||
{ // stop trzeba powtarzać, bo inaczej zatrąbi i pojedzie sam
|
// stop trzeba powtarzać, bo inaczej zatrąbi i pojedzie sam
|
||||||
// if ((MoverParameters->Vel==0.0)||(vmechmax==0.0)) //jeśli jedzie
|
// if ((MoverParameters->Vel==0.0)||(vmechmax==0.0)) //jeśli jedzie lub ma stanąć/stać
|
||||||
// lub ma stanąć/stać
|
|
||||||
{ // nie dostanie komendy jeśli jedzie i ma jechać
|
{ // nie dostanie komendy jeśli jedzie i ma jechać
|
||||||
// PutCommand("ShuntVelocity",vmechmax,e->Params[9].asMemCell->Value2(),&sl,stopSem);
|
// PutCommand("ShuntVelocity",vmechmax,e->Params[9].asMemCell->Value2(),&sl,stopSem);
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
WriteLog(edir + "ShuntVelocity " + AnsiString(vmechmax) + " " +
|
WriteLog(
|
||||||
AnsiString(e->ValueGet(2)));
|
edir + " - [ShuntVelocity] ["
|
||||||
|
+ to_string( vmechmax, 2 ) + "] ["
|
||||||
|
+ to_string( e->ValueGet( 2 ), 2 ) + "]" );
|
||||||
#endif
|
#endif
|
||||||
return (vmechmax > 0) ? cm_ShuntVelocity : cm_Unknown;
|
return (
|
||||||
|
vmechmax > 0 ?
|
||||||
|
cm_ShuntVelocity :
|
||||||
|
cm_Unknown );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((vmechmax != 0.0) && (scandist < 100.0))
|
if ((vmechmax != 0.0) && (scandist < 100.0)) {
|
||||||
{ // jeśli Tm w odległości do 100m podaje zezwolenie na jazdę, to od
|
// jeśli Tm w odległości do 100m podaje zezwolenie na jazdę, to od razu ją ignorujemy, aby móc szukać kolejnej
|
||||||
// razu ją ignorujemy, aby móc szukać kolejnej
|
|
||||||
// eSignSkip=e; //wtedy uznajemy ignorowaną przy poszukiwaniu nowej
|
// eSignSkip=e; //wtedy uznajemy ignorowaną przy poszukiwaniu nowej
|
||||||
#if LOGBACKSCAN
|
#if LOGBACKSCAN
|
||||||
WriteLog(edir + " - will be ignored due to Ms2");
|
WriteLog(edir + " - will be ignored due to Ms2");
|
||||||
#endif
|
#endif
|
||||||
return (vmechmax > 0) ? cm_ShuntVelocity : cm_Unknown;
|
return (
|
||||||
|
vmechmax > 0 ?
|
||||||
|
cm_ShuntVelocity :
|
||||||
|
cm_Unknown );
|
||||||
}
|
}
|
||||||
} // if (move?...
|
} // if (move?...
|
||||||
} // if (OrderCurrentGet()==Shunt)
|
} // if (OrderCurrentGet()==Shunt)
|
||||||
@@ -5644,12 +5708,12 @@ int TController::CrossRoute(TTrack *tr)
|
|||||||
}
|
}
|
||||||
return 0; // nic nie znaleziono?
|
return 0; // nic nie znaleziono?
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
void TController::RouteSwitch(int d)
|
void TController::RouteSwitch(int d)
|
||||||
{ // ustawienie kierunku jazdy z kabiny
|
{ // ustawienie kierunku jazdy z kabiny
|
||||||
d &= 3;
|
d &= 3;
|
||||||
if( d ) {
|
if( ( d != 0 )
|
||||||
if( iRouteWanted != d ) { // nowy kierunek
|
&& ( iRouteWanted != d ) ) { // nowy kierunek
|
||||||
iRouteWanted = d; // zapamiętanie
|
iRouteWanted = d; // zapamiętanie
|
||||||
if( mvOccupied->CategoryFlag & 2 ) {
|
if( mvOccupied->CategoryFlag & 2 ) {
|
||||||
// jeśli samochód
|
// jeśli samochód
|
||||||
@@ -5674,8 +5738,8 @@ void TController::RouteSwitch(int d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
std::string TController::OwnerName() const
|
std::string TController::OwnerName() const
|
||||||
{
|
{
|
||||||
return ( pVehicle ? pVehicle->MoverParameters->Name : "none" );
|
return ( pVehicle ? pVehicle->MoverParameters->Name : "none" );
|
||||||
|
|||||||
16
Driver.h
16
Driver.h
@@ -209,6 +209,7 @@ public:
|
|||||||
double BrakeAccFactor();
|
double BrakeAccFactor();
|
||||||
double fBrakeReaction = 1.0; //opóźnienie zadziałania hamulca - czas w s / (km/h)
|
double fBrakeReaction = 1.0; //opóźnienie zadziałania hamulca - czas w s / (km/h)
|
||||||
double fAccThreshold = 0.0; // próg opóźnienia dla zadziałania hamulca
|
double fAccThreshold = 0.0; // próg opóźnienia dla zadziałania hamulca
|
||||||
|
double AbsAccS_avg = 0.0; // averaged out directional acceleration
|
||||||
double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca
|
double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca
|
||||||
double fBrake_a0[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca
|
double fBrake_a0[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca
|
||||||
double fBrake_a1[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca
|
double fBrake_a1[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca
|
||||||
@@ -230,8 +231,9 @@ private:
|
|||||||
TAction GetAction() {
|
TAction GetAction() {
|
||||||
return eAction; }
|
return eAction; }
|
||||||
bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista
|
bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista
|
||||||
int iRouteWanted = 3; // oczekiwany kierunek jazdy (0-stop,1-lewo,2-prawo,3-prosto) np. odpala
|
/*
|
||||||
// migacz lub czeka na stan zwrotnicy
|
int iRouteWanted = 3; // oczekiwany kierunek jazdy (0-stop,1-lewo,2-prawo,3-prosto) np. odpala migacz lub czeka na stan zwrotnicy
|
||||||
|
*/
|
||||||
private:
|
private:
|
||||||
TDynamicObject *pVehicle = nullptr; // pojazd w którym siedzi sterujący
|
TDynamicObject *pVehicle = nullptr; // pojazd w którym siedzi sterujący
|
||||||
TDynamicObject *pVehicles[2]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
|
TDynamicObject *pVehicles[2]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
|
||||||
@@ -311,10 +313,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
Mtable::TTrainParameters *Timetable() {
|
Mtable::TTrainParameters *Timetable() {
|
||||||
return TrainParams; };
|
return TrainParams; };
|
||||||
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2,
|
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation, TStopReason reason = stopComm);
|
||||||
const TLocation &NewLocation, TStopReason reason = stopComm);
|
bool PutCommand( std::string NewCommand, double NewValue1, double NewValue2, glm::dvec3 const *NewLocation, TStopReason reason = stopComm );
|
||||||
bool PutCommand(std::string NewCommand, double NewValue1, double NewValue2,
|
|
||||||
const vector3 *NewLocation, TStopReason reason = stopComm);
|
|
||||||
void UpdateSituation(double dt); // uruchamiac przynajmniej raz na sekundę
|
void UpdateSituation(double dt); // uruchamiac przynajmniej raz na sekundę
|
||||||
// procedury dotyczace rozkazow dla maszynisty
|
// procedury dotyczace rozkazow dla maszynisty
|
||||||
// uaktualnia informacje o prędkości
|
// uaktualnia informacje o prędkości
|
||||||
@@ -374,7 +374,7 @@ private:
|
|||||||
bool BackwardTrackBusy(TTrack *Track);
|
bool BackwardTrackBusy(TTrack *Track);
|
||||||
TEvent *CheckTrackEventBackward(double fDirection, TTrack *Track);
|
TEvent *CheckTrackEventBackward(double fDirection, TTrack *Track);
|
||||||
TTrack *BackwardTraceRoute(double &fDistance, double &fDirection, TTrack *Track, TEvent *&Event);
|
TTrack *BackwardTraceRoute(double &fDistance, double &fDirection, TTrack *Track, TEvent *&Event);
|
||||||
void SetProximityVelocity(double dist, double vel, const vector3 *pos);
|
void SetProximityVelocity( double dist, double vel, glm::dvec3 const *pos );
|
||||||
TCommandType BackwardScan();
|
TCommandType BackwardScan();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -401,7 +401,9 @@ private:
|
|||||||
void DirectionInitial();
|
void DirectionInitial();
|
||||||
std::string TableText(std::size_t const Index);
|
std::string TableText(std::size_t const Index);
|
||||||
int CrossRoute(TTrack *tr);
|
int CrossRoute(TTrack *tr);
|
||||||
|
/*
|
||||||
void RouteSwitch(int d);
|
void RouteSwitch(int d);
|
||||||
|
*/
|
||||||
std::string OwnerName() const;
|
std::string OwnerName() const;
|
||||||
TMoverParameters const *Controlling() const {
|
TMoverParameters const *Controlling() const {
|
||||||
return mvControlling; }
|
return mvControlling; }
|
||||||
|
|||||||
376
DynObj.cpp
376
DynObj.cpp
@@ -15,34 +15,20 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "DynObj.h"
|
#include "DynObj.h"
|
||||||
|
|
||||||
#include "Logs.h"
|
#include "simulation.h"
|
||||||
#include "MdlMngr.h"
|
|
||||||
#include "Timer.h"
|
|
||||||
#include "usefull.h"
|
|
||||||
// McZapkie-260202
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "renderer.h"
|
#include "Timer.h"
|
||||||
#include "AirCoupler.h"
|
#include "Logs.h"
|
||||||
|
|
||||||
#include "TractionPower.h"
|
|
||||||
#include "Ground.h" //bo Global::pGround->bDynamicRemove
|
|
||||||
#include "Event.h"
|
|
||||||
#include "Driver.h"
|
|
||||||
#include "Camera.h" //bo likwidujemy trzęsienie
|
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include "Traction.h"
|
#include "Traction.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
#include "MdlMngr.h"
|
||||||
|
|
||||||
// Ra: taki zapis funkcjonuje lepiej, ale może nie jest optymalny
|
// Ra: taki zapis funkcjonuje lepiej, ale może nie jest optymalny
|
||||||
#define vWorldFront Math3D::vector3(0, 0, 1)
|
#define vWorldFront Math3D::vector3(0, 0, 1)
|
||||||
#define vWorldUp Math3D::vector3(0, 1, 0)
|
#define vWorldUp Math3D::vector3(0, 1, 0)
|
||||||
#define vWorldLeft CrossProduct(vWorldUp, vWorldFront)
|
#define vWorldLeft CrossProduct(vWorldUp, vWorldFront)
|
||||||
|
|
||||||
// Ra: bo te poniżej to się powielały w każdym module odobno
|
|
||||||
// vector3 vWorldFront=vector3(0,0,1);
|
|
||||||
// vector3 vWorldUp=vector3(0,1,0);
|
|
||||||
// vector3 vWorldLeft=CrossProduct(vWorldUp,vWorldFront);
|
|
||||||
|
|
||||||
#define M_2PI 6.283185307179586476925286766559;
|
#define M_2PI 6.283185307179586476925286766559;
|
||||||
const float maxrot = (float)(M_PI / 3.0); // 60°
|
const float maxrot = (float)(M_PI / 3.0); // 60°
|
||||||
|
|
||||||
@@ -50,6 +36,7 @@ std::string const TDynamicObject::MED_labels[] = {
|
|||||||
"masa: ", "amax: ", "Fzad: ", "FmPN: ", "FmED: ", "FrED: ", "FzPN: ", "nPrF: "
|
"masa: ", "amax: ", "Fzad: ", "FmPN: ", "FmED: ", "FrED: ", "FzPN: ", "nPrF: "
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool TDynamicObject::bDynamicRemove { false };
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void TAnimPant::AKP_4E()
|
void TAnimPant::AKP_4E()
|
||||||
@@ -416,14 +403,22 @@ void TDynamicObject::UpdateDoorTranslate(TAnim *pAnim)
|
|||||||
// Ra: te współczynniki są bez sensu, bo modyfikują wektor przesunięcia
|
// Ra: te współczynniki są bez sensu, bo modyfikują wektor przesunięcia
|
||||||
// w efekcie drzwi otwierane na zewnątrz będą odlatywac dowolnie daleko :)
|
// w efekcie drzwi otwierane na zewnątrz będą odlatywac dowolnie daleko :)
|
||||||
// ograniczyłem zakres ruchu funkcją max
|
// ograniczyłem zakres ruchu funkcją max
|
||||||
if (pAnim->smAnimated)
|
if (pAnim->smAnimated) {
|
||||||
{
|
|
||||||
if (pAnim->iNumber & 1)
|
if( pAnim->iNumber & 1 ) {
|
||||||
pAnim->smAnimated->SetTranslate(
|
pAnim->smAnimated->SetTranslate(
|
||||||
vector3(0, 0, Min0R(dDoorMoveR * pAnim->fSpeed, dDoorMoveR)));
|
vector3{
|
||||||
else
|
0.0,
|
||||||
|
0.0,
|
||||||
|
dDoorMoveR } );
|
||||||
|
}
|
||||||
|
else {
|
||||||
pAnim->smAnimated->SetTranslate(
|
pAnim->smAnimated->SetTranslate(
|
||||||
vector3(0, 0, Min0R(dDoorMoveL * pAnim->fSpeed, dDoorMoveL)));
|
vector3{
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
dDoorMoveL } );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -494,18 +489,30 @@ void TDynamicObject::UpdatePant(TAnim *pAnim)
|
|||||||
|
|
||||||
void TDynamicObject::UpdateDoorPlug(TAnim *pAnim)
|
void TDynamicObject::UpdateDoorPlug(TAnim *pAnim)
|
||||||
{ // animacja drzwi - odskokprzesuw
|
{ // animacja drzwi - odskokprzesuw
|
||||||
if (pAnim->smAnimated)
|
if (pAnim->smAnimated) {
|
||||||
{
|
|
||||||
if (pAnim->iNumber & 1)
|
if( pAnim->iNumber & 1 ) {
|
||||||
pAnim->smAnimated->SetTranslate(
|
pAnim->smAnimated->SetTranslate(
|
||||||
vector3(Min0R(dDoorMoveR * 2, MoverParameters->DoorMaxPlugShift), 0,
|
vector3 {
|
||||||
Max0R(0, Min0R(dDoorMoveR * pAnim->fSpeed, dDoorMoveR) -
|
std::min(
|
||||||
MoverParameters->DoorMaxPlugShift * 0.5f)));
|
dDoorMoveR * 2,
|
||||||
else
|
MoverParameters->DoorMaxPlugShift ),
|
||||||
|
0.0,
|
||||||
|
std::max(
|
||||||
|
0.0,
|
||||||
|
dDoorMoveR - MoverParameters->DoorMaxPlugShift * 0.5 ) } );
|
||||||
|
}
|
||||||
|
else {
|
||||||
pAnim->smAnimated->SetTranslate(
|
pAnim->smAnimated->SetTranslate(
|
||||||
vector3(Min0R(dDoorMoveL * 2, MoverParameters->DoorMaxPlugShift), 0,
|
vector3 {
|
||||||
Max0R(0, Min0R(dDoorMoveL * pAnim->fSpeed, dDoorMoveL) -
|
std::min(
|
||||||
MoverParameters->DoorMaxPlugShift * 0.5f)));
|
dDoorMoveL * 2,
|
||||||
|
MoverParameters->DoorMaxPlugShift ),
|
||||||
|
0.0,
|
||||||
|
std::max(
|
||||||
|
0.0,
|
||||||
|
dDoorMoveL - MoverParameters->DoorMaxPlugShift * 0.5f ) } );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1757,8 +1764,8 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
}
|
}
|
||||||
if (ActPar.find('0') != std::string::npos) // wylaczanie na sztywno
|
if (ActPar.find('0') != std::string::npos) // wylaczanie na sztywno
|
||||||
{
|
{
|
||||||
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
|
|
||||||
MoverParameters->Hamulec->ForceEmptiness();
|
MoverParameters->Hamulec->ForceEmptiness();
|
||||||
|
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
|
||||||
}
|
}
|
||||||
if (ActPar.find('E') != std::string::npos) // oprozniony
|
if (ActPar.find('E') != std::string::npos) // oprozniony
|
||||||
{
|
{
|
||||||
@@ -1782,16 +1789,16 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
{
|
{
|
||||||
if (Random(10) < 1) // losowanie 1/10
|
if (Random(10) < 1) // losowanie 1/10
|
||||||
{
|
{
|
||||||
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
|
|
||||||
MoverParameters->Hamulec->ForceEmptiness();
|
MoverParameters->Hamulec->ForceEmptiness();
|
||||||
|
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ActPar.find('X') != std::string::npos) // agonalny wylaczanie 20%, usrednienie przekladni
|
if (ActPar.find('X') != std::string::npos) // agonalny wylaczanie 20%, usrednienie przekladni
|
||||||
{
|
{
|
||||||
if (Random(100) < 20) // losowanie 20/100
|
if (Random(100) < 20) // losowanie 20/100
|
||||||
{
|
{
|
||||||
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
|
|
||||||
MoverParameters->Hamulec->ForceEmptiness();
|
MoverParameters->Hamulec->ForceEmptiness();
|
||||||
|
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
|
||||||
}
|
}
|
||||||
if (MoverParameters->BrakeCylMult[2] * MoverParameters->BrakeCylMult[1] >
|
if (MoverParameters->BrakeCylMult[2] * MoverParameters->BrakeCylMult[1] >
|
||||||
0.01) // jesli jest nastawiacz mechaniczny PL
|
0.01) // jesli jest nastawiacz mechaniczny PL
|
||||||
@@ -2625,77 +2632,36 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
NoVoltTime = 0;
|
NoVoltTime = 0;
|
||||||
tmpTraction.TractionVoltage = v;
|
tmpTraction.TractionVoltage = v;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
NoVoltTime += dt;
|
||||||
/*
|
if( NoVoltTime > 0.2 ) {
|
||||||
if (MoverParameters->Vel>0.1f) //jeśli jedzie
|
// jeśli brak zasilania dłużej niż 0.2 sekundy (25km/h pod izolatorem daje 0.15s)
|
||||||
if (NoVoltTime==0.0) //tylko przy pierwszym zaniku napięcia
|
// Ra 2F1H: prowizorka, trzeba przechować napięcie, żeby nie wywalało WS pod izolatorem
|
||||||
|
if( MoverParameters->Vel > 0.5 ) {
|
||||||
|
// jeśli jedzie
|
||||||
|
// Ra 2014-07: doraźna blokada logowania zimnych lokomotyw - zrobić to trzeba inaczej
|
||||||
if( MoverParameters->PantFrontUp || MoverParameters->PantRearUp )
|
if( MoverParameters->PantFrontUp || MoverParameters->PantRearUp )
|
||||||
//if
|
|
||||||
((pants[0].fParamPants->PantTraction>1.0)||(pants[1].fParamPants->PantTraction>1.0))
|
|
||||||
{//wspomagacz usuwania problemów z siecią
|
|
||||||
if (!Global::iPause)
|
|
||||||
{//Ra: tymczasowa teleportacja do miejsca, gdzie brakuje prądu
|
|
||||||
Global::SetCameraPosition(vPosition+vector3(0,0,5)); //nowa
|
|
||||||
pozycja dla
|
|
||||||
generowania obiektów
|
|
||||||
Global::pCamera->Init(vPosition+vector3(0,0,5),Global::pFreeCameraInitAngle[0]);
|
|
||||||
//przestawienie
|
|
||||||
}
|
|
||||||
Global:l::pGround->Silence(Global::pCamera->Pos); //wyciszenie
|
|
||||||
wszystkiego
|
|
||||||
z poprzedniej pozycji
|
|
||||||
Globa:iPause|=1; //tymczasowe zapauzowanie, gdy problem z
|
|
||||||
siecią
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
NoVoltTime = NoVoltTime + dt;
|
|
||||||
if (NoVoltTime > 0.2) // jeśli brak zasilania dłużej niż 0.2 sekundy (25km/h pod
|
|
||||||
// izolatorem daje 0.15s)
|
|
||||||
{ // Ra 2F1H: prowizorka, trzeba przechować napięcie, żeby nie wywalało
|
|
||||||
// WS pod
|
|
||||||
// izolatorem
|
|
||||||
if (MoverParameters->Vel > 0.5) // jeśli jedzie
|
|
||||||
if (MoverParameters->PantFrontUp ||
|
|
||||||
MoverParameters->PantRearUp) // Ra 2014-07: doraźna blokada logowania
|
|
||||||
// zimnych lokomotyw - zrobić to trzeba
|
|
||||||
// inaczej
|
|
||||||
// if (NoVoltTime>0.02) //tu można ograniczyć czas rozłączenia
|
// if (NoVoltTime>0.02) //tu można ograniczyć czas rozłączenia
|
||||||
// if (DebugModeFlag) //logowanie nie zawsze
|
// if (DebugModeFlag) //logowanie nie zawsze
|
||||||
if ((MoverParameters->Mains) &&
|
if( ( MoverParameters->Mains )
|
||||||
((MoverParameters->EngineType != ElectricInductionMotor)
|
&& ( ( MoverParameters->EngineType != ElectricInductionMotor )
|
||||||
|| (MoverParameters->GetTrainsetVoltage() < 0.1f)))
|
|| ( MoverParameters->GetTrainsetVoltage() < 0.1f ) ) ) {
|
||||||
{ // Ra 15-01: logować tylko, jeśli WS załączony
|
// Ra 15-01: logować tylko, jeśli WS załączony
|
||||||
// yB 16-03: i nie jest to asynchron zasilany z daleka
|
// yB 16-03: i nie jest to asynchron zasilany z daleka
|
||||||
// if (MoverParameters->PantFrontUp&&pants)
|
|
||||||
// Ra 15-01: bezwzględne współrzędne pantografu nie są dostępne,
|
// Ra 15-01: bezwzględne współrzędne pantografu nie są dostępne,
|
||||||
// więc lepiej się tego nie zaloguje
|
// więc lepiej się tego nie zaloguje
|
||||||
ErrorLog("Voltage loss: by " + MoverParameters->Name + " at " +
|
ErrorLog(
|
||||||
to_string(vPosition.x, 2, 7) + " " +
|
"Bad traction: " + MoverParameters->Name
|
||||||
to_string(vPosition.y, 2, 7) + " " +
|
+ " lost power for " + to_string( NoVoltTime, 2 ) + " sec. at "
|
||||||
to_string(vPosition.z, 2, 7) + ", time " +
|
+ to_string( glm::dvec3{ vPosition } ) );
|
||||||
to_string(NoVoltTime, 2, 7));
|
|
||||||
// if (MoverParameters->PantRearUp)
|
|
||||||
// if (iAnimType[ANIM_PANTS]>1)
|
|
||||||
// if (pants[1])
|
|
||||||
// ErrorLog("Voltage loss: by "+MoverParameters->Name+" at
|
|
||||||
// "+FloatToStrF(vPosition.x,ffFixed,7,2)+"
|
|
||||||
// "+FloatToStrF(vPosition.y,ffFixed,7,2)+"
|
|
||||||
// "+FloatToStrF(vPosition.z,ffFixed,7,2)+", time
|
|
||||||
// "+FloatToStrF(NoVoltTime,ffFixed,7,2));
|
|
||||||
}
|
}
|
||||||
// Ra 2F1H: nie było sensu wpisywać tu zera po upływie czasu, bo
|
}
|
||||||
// zmienna była
|
// Ra 2F1H: nie było sensu wpisywać tu zera po upływie czasu, bo zmienna była
|
||||||
// tymczasowa, a napięcie zerowane od razu
|
// tymczasowa, a napięcie zerowane od razu
|
||||||
tmpTraction.TractionVoltage = 0; // Ra 2013-12: po co tak?
|
tmpTraction.TractionVoltage = 0; // Ra 2013-12: po co tak?
|
||||||
// pControlled->MainSwitch(false); //może tak?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else //Ra: nie no, trzeba podnieść pantografy, jak nie będzie drutu, to
|
|
||||||
// będą miały prąd
|
|
||||||
// po osiągnięciu 1.4m
|
|
||||||
// tmpTraction.TractionVoltage=0.95*MoverParameters->EnginePowerSource.MaxVoltage;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tmpTraction.TractionVoltage = 0.95 * MoverParameters->EnginePowerSource.MaxVoltage;
|
tmpTraction.TractionVoltage = 0.95 * MoverParameters->EnginePowerSource.MaxVoltage;
|
||||||
@@ -2760,9 +2726,9 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
1000; // chwilowy max ED -> do rozdzialu sil
|
1000; // chwilowy max ED -> do rozdzialu sil
|
||||||
FfulED = std::min(p->MoverParameters->eimv[eimv_Fful], 0.0) *
|
FfulED = std::min(p->MoverParameters->eimv[eimv_Fful], 0.0) *
|
||||||
1000; // chwilowy max ED -> do rozdzialu sil
|
1000; // chwilowy max ED -> do rozdzialu sil
|
||||||
FrED -= std::min(p->MoverParameters->eimv[eimv_Fr], 0.0) *
|
FrED -= std::min(p->MoverParameters->eimv[eimv_Fmax], 0.0) *
|
||||||
1000; // chwilowo realizowane ED -> do pneumatyki
|
1000; // chwilowo realizowane ED -> do pneumatyki
|
||||||
Frj += std::max(p->MoverParameters->eimv[eimv_Fr], 0.0) *
|
Frj += std::max(p->MoverParameters->eimv[eimv_Fmax], 0.0) *
|
||||||
1000;// chwilowo realizowany napęd -> do utrzymującego
|
1000;// chwilowo realizowany napęd -> do utrzymującego
|
||||||
masa += p->MoverParameters->TotalMass;
|
masa += p->MoverParameters->TotalMass;
|
||||||
osie += p->MoverParameters->NAxles;
|
osie += p->MoverParameters->NAxles;
|
||||||
@@ -2861,10 +2827,10 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
if ((FzEP[i] > 0.01) &&
|
if ((FzEP[i] > 0.01) &&
|
||||||
(FzEP[i] >
|
(FzEP[i] >
|
||||||
p->MoverParameters->TotalMass * p->MoverParameters->eimc[eimc_p_eped] +
|
p->MoverParameters->TotalMass * p->MoverParameters->eimc[eimc_p_eped] +
|
||||||
Min0R(p->MoverParameters->eimv[eimv_Fr], 0) * 1000) &&
|
Min0R(p->MoverParameters->eimv[eimv_Fmax], 0) * 1000) &&
|
||||||
(!PrzekrF[i]))
|
(!PrzekrF[i]))
|
||||||
{
|
{
|
||||||
float przek1 = -Min0R(p->MoverParameters->eimv[eimv_Fr], 0) * 1000 +
|
float przek1 = -Min0R(p->MoverParameters->eimv[eimv_Fmax], 0) * 1000 +
|
||||||
FzEP[i] -
|
FzEP[i] -
|
||||||
p->MoverParameters->TotalMass *
|
p->MoverParameters->TotalMass *
|
||||||
p->MoverParameters->eimc[eimc_p_eped] * 0.999;
|
p->MoverParameters->eimc[eimc_p_eped] * 0.999;
|
||||||
@@ -2969,19 +2935,13 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
// McZapkie-260202 - dMoveLen przyda sie przy stukocie kol
|
// McZapkie-260202 - dMoveLen przyda sie przy stukocie kol
|
||||||
dDOMoveLen =
|
dDOMoveLen =
|
||||||
GetdMoveLen() + MoverParameters->ComputeMovement(dt, dt1, ts, tp, tmpTraction, l, r);
|
GetdMoveLen() + MoverParameters->ComputeMovement(dt, dt1, ts, tp, tmpTraction, l, r);
|
||||||
// yB: zeby zawsze wrzucalo w jedna strone zakretu
|
|
||||||
/*
|
|
||||||
// this seemed to have opposite effect, if anything -- the sway direction would be affected
|
|
||||||
// by the 'direction' of the track, making the sway go sometimes inward, sometimes outward
|
|
||||||
MoverParameters->AccN *= -ABuGetDirection();
|
|
||||||
*/
|
|
||||||
// if (dDOMoveLen!=0.0) //Ra: nie może być, bo blokuje Event0
|
// if (dDOMoveLen!=0.0) //Ra: nie może być, bo blokuje Event0
|
||||||
if( Mechanik )
|
if( Mechanik )
|
||||||
Mechanik->MoveDistanceAdd( dDOMoveLen ); // dodanie aktualnego przemieszczenia
|
Mechanik->MoveDistanceAdd( dDOMoveLen ); // dodanie aktualnego przemieszczenia
|
||||||
Move(dDOMoveLen);
|
Move(dDOMoveLen);
|
||||||
if (!bEnabled) // usuwane pojazdy nie mają toru
|
if (!bEnabled) // usuwane pojazdy nie mają toru
|
||||||
{ // pojazd do usunięcia
|
{ // pojazd do usunięcia
|
||||||
Global::pGround->bDynamicRemove = true; // sprawdzić
|
bDynamicRemove = true; // sprawdzić
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Global::ABuDebug = dDOMoveLen / dt1;
|
Global::ABuDebug = dDOMoveLen / dt1;
|
||||||
@@ -3218,19 +3178,18 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
if ((MoverParameters->PantRearVolt == 0.0) &&
|
if ((MoverParameters->PantRearVolt == 0.0) &&
|
||||||
(MoverParameters->PantFrontVolt == 0.0) && sPantUp)
|
(MoverParameters->PantFrontVolt == 0.0) && sPantUp)
|
||||||
sPantUp->gain(vol).position(vPosition).play();
|
sPantUp->gain(vol).position(vPosition).play();
|
||||||
if (p->hvPowerWire) // TODO: wyliczyć trzeba prąd przypadający na
|
if (p->hvPowerWire) {
|
||||||
// pantograf i
|
// TODO: wyliczyć trzeba prąd przypadający na pantograf i wstawić do GetVoltage()
|
||||||
// wstawić do GetVoltage()
|
MoverParameters->PantRearVolt = p->hvPowerWire->VoltageGet( MoverParameters->Voltage, fPantCurrent );
|
||||||
{
|
|
||||||
MoverParameters->PantRearVolt =
|
|
||||||
p->hvPowerWire->VoltageGet(MoverParameters->Voltage, fPantCurrent);
|
|
||||||
fCurrent -= fPantCurrent; // taki prąd płynie przez powyższy pantograf
|
fCurrent -= fPantCurrent; // taki prąd płynie przez powyższy pantograf
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
MoverParameters->PantRearVolt = 0.0;
|
MoverParameters->PantRearVolt = 0.0;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
// Global::iPause ^= 2;
|
||||||
MoverParameters->PantRearVolt = 0.0;
|
MoverParameters->PantRearVolt = 0.0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
} // pozostałe na razie nie obsługiwane
|
} // pozostałe na razie nie obsługiwane
|
||||||
if( MoverParameters->PantPress > (
|
if( MoverParameters->PantPress > (
|
||||||
@@ -3297,8 +3256,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
p->fAngleU = acos((p->fLenL1 * cos(k) + p->fHoriz) / p->fLenU1); // górne ramię
|
p->fAngleU = acos((p->fLenL1 * cos(k) + p->fHoriz) / p->fLenU1); // górne ramię
|
||||||
// wyliczyć aktualną wysokość z wzoru sinusowego
|
// wyliczyć aktualną wysokość z wzoru sinusowego
|
||||||
// h=a*sin()+b*sin()
|
// h=a*sin()+b*sin()
|
||||||
p->PantWys = p->fLenL1 * sin(k) + p->fLenU1 * sin(p->fAngleU) +
|
// wysokość całości
|
||||||
p->fHeight; // wysokość całości
|
p->PantWys = p->fLenL1 * sin(k) + p->fLenU1 * sin(p->fAngleU) + p->fHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // koniec pętli po pantografach
|
} // koniec pętli po pantografach
|
||||||
@@ -4183,7 +4142,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
// Ra 15-01: gałka nastawy hamulca
|
// Ra 15-01: gałka nastawy hamulca
|
||||||
parser.getTokens();
|
parser.getTokens();
|
||||||
parser >> asAnimName;
|
parser >> asAnimName;
|
||||||
smBrakeMode = mdModel->GetFromName(asAnimName.c_str());
|
smBrakeMode = mdModel->GetFromName(asAnimName);
|
||||||
// jeszcze wczytać kąty obrotu dla poszczególnych ustawień
|
// jeszcze wczytać kąty obrotu dla poszczególnych ustawień
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4191,7 +4150,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
// Ra 15-01: gałka nastawy hamulca
|
// Ra 15-01: gałka nastawy hamulca
|
||||||
parser.getTokens();
|
parser.getTokens();
|
||||||
parser >> asAnimName;
|
parser >> asAnimName;
|
||||||
smLoadMode = mdModel->GetFromName(asAnimName.c_str());
|
smLoadMode = mdModel->GetFromName(asAnimName);
|
||||||
// jeszcze wczytać kąty obrotu dla poszczególnych ustawień
|
// jeszcze wczytać kąty obrotu dla poszczególnych ustawień
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4203,7 +4162,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
for (i = 0; i < iAnimType[ANIM_WHEELS]; ++i) // liczba osi
|
for (i = 0; i < iAnimType[ANIM_WHEELS]; ++i) // liczba osi
|
||||||
{ // McZapkie-050402: wyszukiwanie kol o nazwie str*
|
{ // McZapkie-050402: wyszukiwanie kol o nazwie str*
|
||||||
asAnimName = token + std::to_string(i + 1);
|
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)
|
if (pAnimations[i].smAnimated)
|
||||||
{ //++iAnimatedAxles;
|
{ //++iAnimatedAxles;
|
||||||
pAnimations[i].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu
|
pAnimations[i].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu
|
||||||
@@ -4344,8 +4303,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ErrorLog("Bad model: " + asFileName + " - missed submodel " +
|
ErrorLog("Bad model: " + asFileName + " - missed submodel " + asAnimName); // brak ramienia
|
||||||
asAnimName); // brak ramienia
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4379,8 +4337,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ErrorLog( "Bad model: " + asFileName + " - missed submodel " +
|
ErrorLog( "Bad model: " + asFileName + " - missed submodel " + asAnimName ); // brak ramienia
|
||||||
asAnimName ); // brak ramienia
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4473,10 +4430,8 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
|
|||||||
// pants[i].fParamPants->vPos.z=0; //niezerowe dla pantografów
|
// pants[i].fParamPants->vPos.z=0; //niezerowe dla pantografów
|
||||||
// asymetrycznych
|
// asymetrycznych
|
||||||
pants[ i ].fParamPants->PantTraction = pants[ i ].fParamPants->PantWys;
|
pants[ i ].fParamPants->PantTraction = pants[ i ].fParamPants->PantWys;
|
||||||
pants[ i ].fParamPants->fWidth =
|
// połowa szerokości ślizgu; jest w "Power: CSW="
|
||||||
0.5 *
|
pants[ i ].fParamPants->fWidth = 0.5 * MoverParameters->EnginePowerSource.CollectorParameters.CSW;
|
||||||
MoverParameters->EnginePowerSource.CollectorParameters
|
|
||||||
.CSW; // połowa szerokości ślizgu; jest w "Power: CSW="
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4955,7 +4910,9 @@ void TDynamicObject::RadioStop()
|
|||||||
if( ( MoverParameters->SecuritySystem.RadioStop )
|
if( ( MoverParameters->SecuritySystem.RadioStop )
|
||||||
&& ( MoverParameters->Radio ) ) {
|
&& ( MoverParameters->Radio ) ) {
|
||||||
// jeśli pojazd ma RadioStop i jest on aktywny
|
// jeśli pojazd ma RadioStop i jest on aktywny
|
||||||
Mechanik->PutCommand( "Emergency_brake", 1.0, 1.0, &vPosition, stopRadio );
|
// HAX cast until math types unification
|
||||||
|
glm::dvec3 pos = static_cast<glm::dvec3>(vPosition);
|
||||||
|
Mechanik->PutCommand( "Emergency_brake", 1.0, 1.0, &pos, stopRadio );
|
||||||
// add onscreen notification for human driver
|
// add onscreen notification for human driver
|
||||||
// TODO: do it selectively for the 'local' driver once the multiplayer is in
|
// TODO: do it selectively for the 'local' driver once the multiplayer is in
|
||||||
if( false == Mechanik->AIControllFlag ) {
|
if( false == Mechanik->AIControllFlag ) {
|
||||||
@@ -5414,3 +5371,166 @@ TDynamicObject::ConnectedEnginePowerSource( TDynamicObject const *Caller ) const
|
|||||||
// ...if we're still here, report lack of power source
|
// ...if we're still here, report lack of power source
|
||||||
return MoverParameters->EnginePowerSource.SourceType;
|
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 ) {
|
||||||
|
if( false == vehicle->bEnabled ) { continue; }
|
||||||
|
// Ra: zmienić warunek na sprawdzanie pantografów w jednej zmiennej: czy pantografy i czy podniesione
|
||||||
|
if( vehicle->MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) {
|
||||||
|
update_traction( 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 (TDynamicObject::bDynamicRemove)
|
||||||
|
{ // jeśli jest coś do usunięcia z listy, to trzeba na końcu
|
||||||
|
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
||||||
|
if ( false == Current->DynamicObject->bEnabled)
|
||||||
|
{
|
||||||
|
DynamicRemove(Current->DynamicObject); // usunięcie tego i podłączonych
|
||||||
|
Current = nRootDynamic; // sprawdzanie listy od początku
|
||||||
|
}
|
||||||
|
TDynamicObject::bDynamicRemove = false; // na razie koniec
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, checks for presence and height of traction wire for specified vehicle
|
||||||
|
void
|
||||||
|
vehicle_table::update_traction( TDynamicObject *Vehicle ) {
|
||||||
|
|
||||||
|
auto const vFront = glm::make_vec3( Vehicle->VectorFront().getArray() ); // wektor normalny dla płaszczyzny ruchu pantografu
|
||||||
|
auto const vUp = glm::make_vec3( Vehicle->VectorUp().getArray() ); // wektor pionu pudła (pochylony od pionu na przechyłce)
|
||||||
|
auto const vLeft = glm::make_vec3( Vehicle->VectorLeft().getArray() ); // wektor odległości w bok (odchylony od poziomu na przechyłce)
|
||||||
|
auto const position = glm::dvec3 { Vehicle->GetPosition() }; // współrzędne środka pojazdu
|
||||||
|
|
||||||
|
for( int pantographindex = 0; pantographindex < Vehicle->iAnimType[ ANIM_PANTS ]; ++pantographindex ) {
|
||||||
|
// pętla po pantografach
|
||||||
|
auto pantograph { Vehicle->pants[ pantographindex ].fParamPants };
|
||||||
|
if( true == (
|
||||||
|
pantographindex == TMoverParameters::side::front ?
|
||||||
|
Vehicle->MoverParameters->PantFrontUp :
|
||||||
|
Vehicle->MoverParameters->PantRearUp ) ) {
|
||||||
|
// jeśli pantograf podniesiony
|
||||||
|
auto const pant0 { position + ( vLeft * pantograph->vPos.z ) + ( vUp * pantograph->vPos.y ) + ( vFront * pantograph->vPos.x ) };
|
||||||
|
if( pantograph->hvPowerWire != nullptr ) {
|
||||||
|
// jeżeli znamy drut z poprzedniego przebiegu
|
||||||
|
for( int attempts = 0; attempts < 30; ++attempts ) {
|
||||||
|
// powtarzane aż do znalezienia odpowiedniego odcinka na liście dwukierunkowej
|
||||||
|
if( pantograph->hvPowerWire->iLast & 0x3 ) {
|
||||||
|
// dla ostatniego i przedostatniego przęsła wymuszamy szukanie innego
|
||||||
|
// nie to, że nie ma, ale trzeba sprawdzić inne
|
||||||
|
pantograph->hvPowerWire = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( pantograph->hvPowerWire->hvParallel ) {
|
||||||
|
// jeśli przęsło tworzy bieżnię wspólną, to trzeba sprawdzić pozostałe
|
||||||
|
// nie to, że nie ma, ale trzeba sprawdzić inne
|
||||||
|
pantograph->hvPowerWire = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// obliczamy wyraz wolny równania płaszczyzny (to miejsce nie jest odpowienie)
|
||||||
|
// podstawiamy równanie parametryczne drutu do równania płaszczyzny pantografu
|
||||||
|
auto const fRaParam =
|
||||||
|
-( glm::dot( pantograph->hvPowerWire->pPoint1, vFront ) - glm::dot( pant0, vFront ) )
|
||||||
|
/ glm::dot( pantograph->hvPowerWire->vParametric, vFront );
|
||||||
|
|
||||||
|
if( fRaParam < -0.001 ) {
|
||||||
|
// histereza rzędu 7cm na 70m typowego przęsła daje 1 promil
|
||||||
|
pantograph->hvPowerWire = pantograph->hvPowerWire->hvNext[ 0 ];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( fRaParam > 1.001 ) {
|
||||||
|
pantograph->hvPowerWire = pantograph->hvPowerWire->hvNext[ 1 ];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// jeśli t jest w przedziale, wyznaczyć odległość wzdłuż wektorów vUp i vLeft
|
||||||
|
// punkt styku płaszczyzny z drutem (dla generatora łuku el.)
|
||||||
|
auto const vStyk { pantograph->hvPowerWire->pPoint1 + fRaParam * pantograph->hvPowerWire->vParametric };
|
||||||
|
auto const vGdzie { vStyk - pant0 }; // wektor
|
||||||
|
// odległość w pionie musi być w zasięgu ruchu "pionowego" pantografu
|
||||||
|
// musi się mieścić w przedziale ruchu pantografu
|
||||||
|
auto const fVertical { glm::dot( vGdzie, vUp ) };
|
||||||
|
// odległość w bok powinna być mniejsza niż pół szerokości pantografu
|
||||||
|
// to się musi mieścić w przedziale zależnym od szerokości pantografu
|
||||||
|
auto const fHorizontal { std::abs( glm::dot( vGdzie, vLeft ) ) - pantograph->fWidth };
|
||||||
|
// jeśli w pionie albo w bok jest za daleko, to dany drut jest nieużyteczny
|
||||||
|
if( fHorizontal <= 0.0 ) {
|
||||||
|
// koniec pętli, aktualny drut pasuje
|
||||||
|
pantograph->PantTraction = fVertical;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// the wire is outside contact area and as of now we don't have good detection of parallel sections
|
||||||
|
// as such there's no guaratee there isn't parallel section present.
|
||||||
|
// therefore we don't bother checking if the wire is still within range of guide horns
|
||||||
|
// but simply force area search for potential better option
|
||||||
|
pantograph->hvPowerWire = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pantograph->hvPowerWire == nullptr ) {
|
||||||
|
// look in the region for a suitable traction piece if we don't already have any
|
||||||
|
simulation::Region->update_traction( Vehicle, pantographindex );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( pantograph->hvPowerWire == nullptr )
|
||||||
|
&& ( false == Global::bLiveTraction ) ) {
|
||||||
|
// jeśli drut nie znaleziony ale można oszukiwać to dajemy coś tam dla picu
|
||||||
|
Vehicle->pants[ pantographindex ].fParamPants->PantTraction = 1.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// pantograph is down
|
||||||
|
pantograph->hvPowerWire = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, sends list of vehicles over network
|
||||||
|
void
|
||||||
|
vehicle_table::DynamicList( bool const Onlycontrolled ) const {
|
||||||
|
// odesłanie nazw pojazdów dostępnych na scenerii (nazwy, szczególnie wagonów, mogą się powtarzać!)
|
||||||
|
for( auto const *vehicle : m_items ) {
|
||||||
|
if( ( false == Onlycontrolled )
|
||||||
|
|| ( vehicle->Mechanik != nullptr ) ) {
|
||||||
|
// same nazwy pojazdów
|
||||||
|
multiplayer::WyslijString( vehicle->asName, 6 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// informacja o końcu listy
|
||||||
|
multiplayer::WyslijString( "none", 6 );
|
||||||
|
}
|
||||||
|
|||||||
192
DynObj.h
192
DynObj.h
@@ -149,6 +149,9 @@ class TDynamicObject { // klasa pojazdu
|
|||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool bDynamicRemove; // moved from ground
|
||||||
|
|
||||||
private: // położenie pojazdu w świecie oraz parametry ruchu
|
private: // położenie pojazdu w świecie oraz parametry ruchu
|
||||||
Math3D::vector3 vPosition; // Ra: pozycja pojazdu liczona zaraz po przesunięciu
|
Math3D::vector3 vPosition; // Ra: pozycja pojazdu liczona zaraz po przesunięciu
|
||||||
Math3D::vector3 vCoulpler[ 2 ]; // współrzędne sprzęgów do liczenia zderzeń czołowych
|
Math3D::vector3 vCoulpler[ 2 ]; // współrzędne sprzęgów do liczenia zderzeń czołowych
|
||||||
@@ -158,19 +161,17 @@ private: // położenie pojazdu w świecie oraz parametry ruchu
|
|||||||
TTrackParam tp; // parametry toru przekazywane do fizyki
|
TTrackParam tp; // parametry toru przekazywane do fizyki
|
||||||
TTrackFollower Axle0; // oś z przodu (od sprzęgu 0)
|
TTrackFollower Axle0; // oś z przodu (od sprzęgu 0)
|
||||||
TTrackFollower Axle1; // oś z tyłu (od sprzęgu 1)
|
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
|
int iAxleFirst; // numer pierwszej osi w kierunku ruchu (oś wiążąca pojazd z torem i wyzwalająca eventy)
|
||||||
// eventy)
|
|
||||||
float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia
|
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!!!
|
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 );
|
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 asTrack; // nazwa toru początkowego; wywalić?
|
||||||
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
|
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
|
||||||
Math3D::matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
|
Math3D::matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
|
||||||
TMoverParameters *MoverParameters; // parametry fizyki ruchu oraz przeliczanie
|
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 *NextConnected; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
|
||||||
TDynamicObject *PrevConnected; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
|
TDynamicObject *PrevConnected; // pojazd podłączony od strony sprzęgu 0 (kabina 1)
|
||||||
int NextConnectedNo; // numer sprzęgu podłączonego z tyłu
|
int NextConnectedNo; // numer sprzęgu podłączonego z tyłu
|
||||||
@@ -180,7 +181,7 @@ public: // parametry położenia pojazdu dostępne publicznie
|
|||||||
|
|
||||||
TPowerSource ConnectedEnginePowerSource( TDynamicObject const *Caller ) const;
|
TPowerSource ConnectedEnginePowerSource( TDynamicObject const *Caller ) const;
|
||||||
|
|
||||||
public: // modele składowe pojazdu
|
// modele składowe pojazdu
|
||||||
TModel3d *mdModel; // model pudła
|
TModel3d *mdModel; // model pudła
|
||||||
TModel3d *mdLoad; // model zmiennego ładunku
|
TModel3d *mdLoad; // model zmiennego ładunku
|
||||||
TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h
|
TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h
|
||||||
@@ -199,7 +200,8 @@ public: // modele składowe pojazdu
|
|||||||
bool SectionLightsActive { false }; // flag indicating whether section lights were set.
|
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?)
|
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;
|
material_data m_materialdata;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -215,12 +217,9 @@ public: // modele składowe pojazdu
|
|||||||
TAnim *pAnimations; // obiekty animujące (zawierają wskaźnik do funkcji wykonującej animację)
|
TAnim *pAnimations; // obiekty animujące (zawierają wskaźnik do funkcji wykonującej animację)
|
||||||
*/
|
*/
|
||||||
std::vector<TAnim> pAnimations;
|
std::vector<TAnim> pAnimations;
|
||||||
TSubModel **
|
TSubModel ** pAnimated; // lista animowanych submodeli (może być ich więcej niż obiektów animujących)
|
||||||
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
|
||||||
double dWheelAngle[3]; // kąty obrotu kół: 0=przednie toczne, 1=napędzające i wiązary, 2=tylne
|
void UpdateNone(TAnim *pAnim){}; // animacja pusta (funkcje ustawiania submodeli, gdy blisko kamery)
|
||||||
// toczne
|
|
||||||
void
|
|
||||||
UpdateNone(TAnim *pAnim){}; // animacja pusta (funkcje ustawiania submodeli, gdy blisko kamery)
|
|
||||||
void UpdateAxle(TAnim *pAnim); // animacja osi
|
void UpdateAxle(TAnim *pAnim); // animacja osi
|
||||||
void UpdateBoogie(TAnim *pAnim); // animacja wózka
|
void UpdateBoogie(TAnim *pAnim); // animacja wózka
|
||||||
void UpdateDoorTranslate(TAnim *pAnim); // animacja drzwi - przesuw
|
void UpdateDoorTranslate(TAnim *pAnim); // animacja drzwi - przesuw
|
||||||
@@ -266,8 +265,7 @@ public: // modele składowe pojazdu
|
|||||||
|
|
||||||
TButton btCoupler1; // sprzegi
|
TButton btCoupler1; // sprzegi
|
||||||
TButton btCoupler2;
|
TButton btCoupler2;
|
||||||
TAirCoupler
|
TAirCoupler btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
|
||||||
btCPneumatic1; // sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
|
|
||||||
TAirCoupler btCPneumatic2;
|
TAirCoupler btCPneumatic2;
|
||||||
TAirCoupler btCPneumatic1r; // ABu: to zeby nie bylo problemow przy laczeniu wagonow,
|
TAirCoupler btCPneumatic1r; // ABu: to zeby nie bylo problemow przy laczeniu wagonow,
|
||||||
TAirCoupler btCPneumatic2r; // jesli beda polaczone sprzegami 1<->1 lub 0<->0
|
TAirCoupler btCPneumatic2r; // jesli beda polaczone sprzegami 1<->1 lub 0<->0
|
||||||
@@ -298,8 +296,6 @@ public: // modele składowe pojazdu
|
|||||||
TButton btHeadSignals23;
|
TButton btHeadSignals23;
|
||||||
TButton btMechanik1;
|
TButton btMechanik1;
|
||||||
TButton btMechanik2;
|
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
|
double enginevolume; // MC: pomocnicze zeby gladziej silnik buczal
|
||||||
|
|
||||||
int iAxles; // McZapkie: to potem mozna skasowac i zastapic iNumAxles
|
int iAxles; // McZapkie: to potem mozna skasowac i zastapic iNumAxles
|
||||||
@@ -323,7 +319,6 @@ public: // modele składowe pojazdu
|
|||||||
sound* sReleaser = nullptr;
|
sound* sReleaser = nullptr;
|
||||||
|
|
||||||
// Winger 010304
|
// Winger 010304
|
||||||
// sound* rsPanTup; //PSound sPantUp;
|
|
||||||
sound* sPantUp = nullptr;
|
sound* sPantUp = nullptr;
|
||||||
sound* sPantDown = nullptr;
|
sound* sPantDown = nullptr;
|
||||||
sound* rsDoorOpen = nullptr; // Ra: przeniesione z kabiny
|
sound* rsDoorOpen = nullptr; // Ra: przeniesione z kabiny
|
||||||
@@ -350,8 +345,6 @@ public: // modele składowe pojazdu
|
|||||||
int iHornWarning; // numer syreny do użycia po otrzymaniu sygnału do jazdy
|
int iHornWarning; // numer syreny do użycia po otrzymaniu sygnału do jazdy
|
||||||
bool bEnabled; // Ra: wyjechał na portal i ma być usunięty
|
bool bEnabled; // Ra: wyjechał na portal i ma być usunięty
|
||||||
protected:
|
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
|
int iNumAxles; // ilość osi
|
||||||
std::string asModel;
|
std::string asModel;
|
||||||
|
|
||||||
@@ -371,26 +364,18 @@ public: // modele składowe pojazdu
|
|||||||
TDynamicObject * PrevC(int C);
|
TDynamicObject * PrevC(int C);
|
||||||
TDynamicObject * NextC(int C);
|
TDynamicObject * NextC(int C);
|
||||||
double NextDistance(double d = -1.0);
|
double NextDistance(double d = -1.0);
|
||||||
void SetdMoveLen(double dMoveLen)
|
void SetdMoveLen(double dMoveLen) {
|
||||||
{
|
MoverParameters->dMoveLen = dMoveLen; }
|
||||||
MoverParameters->dMoveLen = dMoveLen;
|
void ResetdMoveLen() {
|
||||||
}
|
MoverParameters->dMoveLen = 0; }
|
||||||
void ResetdMoveLen()
|
double GetdMoveLen() {
|
||||||
{
|
return MoverParameters->dMoveLen; }
|
||||||
MoverParameters->dMoveLen = 0;
|
|
||||||
}
|
|
||||||
double GetdMoveLen()
|
|
||||||
{
|
|
||||||
return MoverParameters->dMoveLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetPneumatic(bool front, bool red);
|
int GetPneumatic(bool front, bool red);
|
||||||
void SetPneumatic(bool front, bool red);
|
void SetPneumatic(bool front, bool red);
|
||||||
std::string asName;
|
std::string asName;
|
||||||
std::string GetName()
|
std::string name() const {
|
||||||
{
|
return this ? asName : std::string(); };
|
||||||
return this ? asName : std::string("");
|
|
||||||
};
|
|
||||||
|
|
||||||
sound* rsDiesielInc = nullptr; // youBy
|
sound* rsDiesielInc = nullptr; // youBy
|
||||||
sound* rscurve = nullptr; // youBy
|
sound* rscurve = nullptr; // youBy
|
||||||
@@ -403,7 +388,6 @@ public: // modele składowe pojazdu
|
|||||||
TDynamicObject * ABuScanNearestObject(TTrack *Track, double ScanDir, double ScanDist,
|
TDynamicObject * ABuScanNearestObject(TTrack *Track, double ScanDir, double ScanDist,
|
||||||
int &CouplNr);
|
int &CouplNr);
|
||||||
TDynamicObject * GetFirstDynamic(int cpl_type, int cf = 1);
|
TDynamicObject * GetFirstDynamic(int cpl_type, int cf = 1);
|
||||||
// TDynamicObject* GetFirstCabDynamic(int cpl_type);
|
|
||||||
void ABuSetModelShake( Math3D::vector3 mShake);
|
void ABuSetModelShake( Math3D::vector3 mShake);
|
||||||
|
|
||||||
// McZapkie-010302
|
// McZapkie-010302
|
||||||
@@ -435,99 +419,65 @@ public: // modele składowe pojazdu
|
|||||||
void Move(double fDistance);
|
void Move(double fDistance);
|
||||||
void FastMove(double fDistance);
|
void FastMove(double fDistance);
|
||||||
void RenderSounds();
|
void RenderSounds();
|
||||||
inline Math3D::vector3 GetPosition() const
|
inline Math3D::vector3 GetPosition() const {
|
||||||
{
|
return vPosition; };
|
||||||
return vPosition;
|
// pobranie współrzędnych czoła
|
||||||
};
|
inline Math3D::vector3 HeadPosition() {
|
||||||
inline Math3D::vector3 HeadPosition()
|
return vCoulpler[iDirection ^ 1]; };
|
||||||
{
|
// pobranie współrzędnych tyłu
|
||||||
return vCoulpler[iDirection ^ 1];
|
inline Math3D::vector3 RearPosition() {
|
||||||
}; // pobranie współrzędnych czoła
|
return vCoulpler[iDirection]; };
|
||||||
inline Math3D::vector3 RearPosition()
|
inline Math3D::vector3 AxlePositionGet() {
|
||||||
{
|
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition; };
|
||||||
return vCoulpler[iDirection];
|
inline Math3D::vector3 VectorFront() const {
|
||||||
}; // pobranie współrzędnych tyłu
|
return vFront; };
|
||||||
inline Math3D::vector3 AxlePositionGet()
|
inline Math3D::vector3 VectorUp() {
|
||||||
{
|
return vUp; };
|
||||||
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition;
|
inline Math3D::vector3 VectorLeft() const {
|
||||||
};
|
return vLeft; };
|
||||||
inline Math3D::vector3 VectorFront() const
|
inline double * Matrix() {
|
||||||
{
|
return mMatrix.getArray(); };
|
||||||
return vFront;
|
inline double GetVelocity() {
|
||||||
};
|
return MoverParameters->Vel; };
|
||||||
inline Math3D::vector3 VectorUp()
|
inline double GetLength() const {
|
||||||
{
|
return MoverParameters->Dim.L; };
|
||||||
return vUp;
|
inline double GetWidth() const {
|
||||||
};
|
return MoverParameters->Dim.W; };
|
||||||
inline Math3D::vector3 VectorLeft() const
|
inline TTrack * GetTrack() {
|
||||||
{
|
return (iAxleFirst ? Axle1.GetTrack() : Axle0.GetTrack()); };
|
||||||
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();
|
|
||||||
|
|
||||||
// McZapkie-260202
|
// McZapkie-260202
|
||||||
void LoadMMediaFile(std::string BaseDir, std::string TypeName, std::string ReplacableSkin);
|
void LoadMMediaFile(std::string BaseDir, std::string TypeName, std::string ReplacableSkin);
|
||||||
|
|
||||||
inline double ABuGetDirection() const // ABu.
|
inline double ABuGetDirection() const { // ABu.
|
||||||
{
|
return (Axle1.GetTrack() == MyTrack ? Axle1.GetDirection() : Axle0.GetDirection()); };
|
||||||
return (Axle1.GetTrack() == MyTrack ? Axle1.GetDirection() : Axle0.GetDirection());
|
// zwraca kierunek pojazdu na torze z aktywną osą
|
||||||
};
|
inline double RaDirectionGet() {
|
||||||
// inline double ABuGetTranslation() //ABu.
|
return iAxleFirst ? Axle1.GetDirection() : Axle0.GetDirection(); };
|
||||||
// {//zwraca przesunięcie wózka względem Point1 toru
|
// zwraca przesunięcie wózka względem Point1 toru z aktywną osią
|
||||||
// return (Axle1.GetTrack()==MyTrack?Axle1.GetTranslation():Axle0.GetTranslation());
|
inline double RaTranslationGet() {
|
||||||
// };
|
return iAxleFirst ? Axle1.GetTranslation() : Axle0.GetTranslation(); };
|
||||||
inline double RaDirectionGet()
|
// zwraca tor z aktywną osią
|
||||||
{ // zwraca kierunek pojazdu na torze z aktywną osą
|
inline TTrack * RaTrackGet() {
|
||||||
return iAxleFirst ? Axle1.GetDirection() : Axle0.GetDirection();
|
return iAxleFirst ? Axle1.GetTrack() : Axle0.GetTrack(); };
|
||||||
};
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
void CouplersDettach(double MinDist, int MyScanDir);
|
void CouplersDettach(double MinDist, int MyScanDir);
|
||||||
void RadioStop();
|
void RadioStop();
|
||||||
void Damage(char flag);
|
void Damage(char flag);
|
||||||
void RaLightsSet(int head, int rear);
|
void RaLightsSet(int head, int rear);
|
||||||
// void RaAxleEvent(TEvent *e);
|
|
||||||
TDynamicObject * FirstFind(int &coupler_nr, int cf = 1);
|
TDynamicObject * FirstFind(int &coupler_nr, int cf = 1);
|
||||||
float GetEPP(); // wyliczanie sredniego cisnienia w PG
|
float GetEPP(); // wyliczanie sredniego cisnienia w PG
|
||||||
int DirectionSet(int d); // ustawienie kierunku w składzie
|
int DirectionSet(int d); // ustawienie kierunku w składzie
|
||||||
int DirectionGet()
|
// odczyt kierunku w składzie
|
||||||
{
|
int DirectionGet() {
|
||||||
return iDirection + iDirection - 1;
|
return iDirection + iDirection - 1; };
|
||||||
}; // odczyt kierunku w składzie
|
|
||||||
int DettachStatus(int dir);
|
int DettachStatus(int dir);
|
||||||
int Dettach(int dir);
|
int Dettach(int dir);
|
||||||
TDynamicObject * Neightbour(int &dir);
|
TDynamicObject * Neightbour(int &dir);
|
||||||
void CoupleDist();
|
void CoupleDist();
|
||||||
TDynamicObject * ControlledFind();
|
TDynamicObject * ControlledFind();
|
||||||
void ParamSet(int what, int into);
|
void ParamSet(int what, int into);
|
||||||
int RouteWish(TTrack *tr); // zapytanie do AI, po którym segmencie skrzyżowania
|
// zapytanie do AI, po którym segmencie skrzyżowania jechać
|
||||||
// jechać
|
int RouteWish(TTrack *tr);
|
||||||
void DestinationSet(std::string to, std::string numer);
|
void DestinationSet(std::string to, std::string numer);
|
||||||
std::string TextureTest(std::string const &name);
|
std::string TextureTest(std::string const &name);
|
||||||
void OverheadTrack(float o);
|
void OverheadTrack(float o);
|
||||||
@@ -535,4 +485,20 @@ public: // modele składowe pojazdu
|
|||||||
static std::string const MED_labels[ 8 ];
|
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 );
|
||||||
|
// legacy method, checks for presence and height of traction wire for specified vehicle
|
||||||
|
void
|
||||||
|
update_traction( TDynamicObject *Vehicle );
|
||||||
|
// legacy method, sends list of vehicles over network
|
||||||
|
void
|
||||||
|
DynamicList( bool const Onlycontrolled = false ) const;
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
17
EU07.cpp
17
EU07.cpp
@@ -20,7 +20,10 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
|
|||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "World.h"
|
||||||
|
#include "simulation.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
#include "Timer.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "keyboardinput.h"
|
#include "keyboardinput.h"
|
||||||
#include "mouseinput.h"
|
#include "mouseinput.h"
|
||||||
@@ -332,16 +335,6 @@ int main(int argc, char *argv[])
|
|||||||
BaseWindowProc = (WNDPROC)::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc );
|
BaseWindowProc = (WNDPROC)::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc );
|
||||||
// switch off the topmost flag
|
// switch off the topmost flag
|
||||||
::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
||||||
|
|
||||||
const HANDLE icon = ::LoadImage(
|
|
||||||
::GetModuleHandle( 0 ),
|
|
||||||
MAKEINTRESOURCE( IDI_ICON1 ),
|
|
||||||
IMAGE_ICON,
|
|
||||||
::GetSystemMetrics( SM_CXSMICON ),
|
|
||||||
::GetSystemMetrics( SM_CYSMICON ),
|
|
||||||
0 );
|
|
||||||
if( icon )
|
|
||||||
::SendMessage( Hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>( icon ) );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -419,9 +412,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
|
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
|
||||||
delete pConsole;
|
SafeDelete( pConsole );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SafeDelete( simulation::Region );
|
||||||
|
|
||||||
glfwDestroyWindow(window);
|
glfwDestroyWindow(window);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|
||||||
|
|||||||
51
EvLaunch.cpp
51
EvLaunch.cpp
@@ -17,36 +17,14 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "EvLaunch.h"
|
#include "EvLaunch.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "usefull.h"
|
|
||||||
#include "McZapkie/mctools.h"
|
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "MemCell.h"
|
#include "MemCell.h"
|
||||||
#include "mtable.h"
|
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
|
|
||||||
using namespace Mtable;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TEventLauncher::TEventLauncher()
|
|
||||||
{ // ustawienie początkowych wartości dla wszystkich zmiennych
|
|
||||||
iKey = 0;
|
|
||||||
DeltaTime = -1;
|
|
||||||
UpdatedTime = 0;
|
|
||||||
fVal1 = fVal2 = 0;
|
|
||||||
iHour = iMinute = -1; // takiego czasu nigdy nie będzie
|
|
||||||
dRadius = 0;
|
|
||||||
Event1 = Event2 = NULL;
|
|
||||||
MemCell = NULL;
|
|
||||||
iCheckMask = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TEventLauncher::Init()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// encodes expected key in a short, where low byte represents the actual key,
|
// encodes expected key in a short, where low byte represents the actual key,
|
||||||
// and the high byte holds modifiers: 0x1 = shift, 0x2 = ctrl, 0x4 = alt
|
// and the high byte holds modifiers: 0x1 = shift, 0x2 = ctrl, 0x4 = alt
|
||||||
int vk_to_glfw_key( int const Keycode ) {
|
int vk_to_glfw_key( int const Keycode ) {
|
||||||
@@ -145,9 +123,9 @@ bool TEventLauncher::Load(cParser *parser)
|
|||||||
*parser >> token;
|
*parser >> token;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
bool TEventLauncher::Render()
|
bool TEventLauncher::check_conditions()
|
||||||
{ //"renderowanie" wyzwalacza
|
{ //"renderowanie" wyzwalacza
|
||||||
bool bCond = false;
|
bool bCond = false;
|
||||||
if (iKey != 0)
|
if (iKey != 0)
|
||||||
@@ -199,13 +177,20 @@ bool TEventLauncher::Render()
|
|||||||
return bCond; // sprawdzanie dRadius w Ground.cpp
|
return bCond; // sprawdzanie dRadius w Ground.cpp
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TEventLauncher::IsGlobal()
|
// sprawdzenie, czy jest globalnym wyzwalaczem czasu
|
||||||
{ // sprawdzenie, czy jest globalnym wyzwalaczem czasu
|
bool TEventLauncher::IsGlobal() const {
|
||||||
if (DeltaTime == 0)
|
|
||||||
if (iHour >= 0)
|
return ( ( DeltaTime == 0 )
|
||||||
if (iMinute >= 0)
|
&& ( iHour >= 0 )
|
||||||
if (dRadius < 0.0) // bez ograniczenia zasięgu
|
&& ( iMinute >= 0 )
|
||||||
return true;
|
&& ( dRadius < 0.0 ) ); // bez ograniczenia zasięgu
|
||||||
return false;
|
}
|
||||||
};
|
|
||||||
|
// calculates node's bounding radius
|
||||||
|
void
|
||||||
|
TEventLauncher::radius_() {
|
||||||
|
|
||||||
|
m_area.radius = std::sqrt( dRadius );
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
58
EvLaunch.h
58
EvLaunch.h
@@ -10,32 +10,48 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Classes.h"
|
|
||||||
|
|
||||||
class TEventLauncher
|
#include "Classes.h"
|
||||||
{
|
#include "scenenode.h"
|
||||||
private:
|
|
||||||
int iKey;
|
class TEventLauncher : public editor::basic_node {
|
||||||
double DeltaTime;
|
|
||||||
double UpdatedTime;
|
|
||||||
double fVal1;
|
|
||||||
double fVal2;
|
|
||||||
std::string szText;
|
|
||||||
int iHour, iMinute; // minuta uruchomienia
|
|
||||||
public:
|
public:
|
||||||
double dRadius;
|
// constructor
|
||||||
|
TEventLauncher( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||||
|
// legacy constructor
|
||||||
|
TEventLauncher() = default;
|
||||||
|
|
||||||
|
// methods
|
||||||
|
bool Load( cParser *parser );
|
||||||
|
// checks conditions associated with the event. returns: true if the conditions are met
|
||||||
|
bool check_conditions();
|
||||||
|
bool IsGlobal() const;
|
||||||
|
// members
|
||||||
std::string asEvent1Name;
|
std::string asEvent1Name;
|
||||||
std::string asEvent2Name;
|
std::string asEvent2Name;
|
||||||
std::string asMemCellName;
|
std::string asMemCellName;
|
||||||
TEvent *Event1;
|
TEvent *Event1 { nullptr };
|
||||||
TEvent *Event2;
|
TEvent *Event2 { nullptr };
|
||||||
TMemCell *MemCell;
|
TMemCell *MemCell { nullptr };
|
||||||
int iCheckMask;
|
int iCheckMask { 0 };
|
||||||
TEventLauncher();
|
double dRadius { 0.0 };
|
||||||
void Init();
|
|
||||||
bool Load(cParser *parser);
|
protected:
|
||||||
bool Render();
|
// calculates node's bounding radius
|
||||||
bool IsGlobal();
|
void
|
||||||
|
radius_();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// members
|
||||||
|
int iKey { 0 };
|
||||||
|
double DeltaTime { -1.0 };
|
||||||
|
double UpdatedTime { 0.0 };
|
||||||
|
double fVal1 { 0.0 };
|
||||||
|
double fVal2 { 0.0 };
|
||||||
|
std::string szText;
|
||||||
|
int iHour { -1 };
|
||||||
|
int iMinute { -1 }; // minuta uruchomienia
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
81
Event.h
81
Event.h
@@ -12,8 +12,9 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
|
#include "Names.h"
|
||||||
using namespace Math3D;
|
#include "scenenode.h"
|
||||||
|
#include "EvLaunch.h"
|
||||||
|
|
||||||
enum TEventType {
|
enum TEventType {
|
||||||
tp_Unknown,
|
tp_Unknown,
|
||||||
@@ -32,7 +33,7 @@ enum TEventType {
|
|||||||
tp_TrackVel,
|
tp_TrackVel,
|
||||||
tp_Multiple,
|
tp_Multiple,
|
||||||
tp_AddValues,
|
tp_AddValues,
|
||||||
tp_Ignored,
|
// tp_Ignored, // NOTE: refactored to separate flag
|
||||||
tp_CopyValues,
|
tp_CopyValues,
|
||||||
tp_WhoIs,
|
tp_WhoIs,
|
||||||
tp_LogValues,
|
tp_LogValues,
|
||||||
@@ -63,7 +64,8 @@ union TParam
|
|||||||
{
|
{
|
||||||
void *asPointer;
|
void *asPointer;
|
||||||
TMemCell *asMemCell;
|
TMemCell *asMemCell;
|
||||||
TGroundNode *nGroundNode;
|
editor::basic_node *asEditorNode;
|
||||||
|
glm::dvec3 const *asLocation;
|
||||||
TTrack *asTrack;
|
TTrack *asTrack;
|
||||||
TAnimModel *asModel;
|
TAnimModel *asModel;
|
||||||
TAnimContainer *asAnimContainer;
|
TAnimContainer *asAnimContainer;
|
||||||
@@ -86,11 +88,10 @@ class TEvent // zmienne: ev*
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
std::string asName;
|
std::string asName;
|
||||||
|
bool m_ignored { false }; // replacement for tp_ignored
|
||||||
bool bEnabled = false; // false gdy ma nie być dodawany do kolejki (skanowanie sygnałów)
|
bool bEnabled = false; // false gdy ma nie być dodawany do kolejki (skanowanie sygnałów)
|
||||||
int iQueued = 0; // ile razy dodany do kolejki
|
int iQueued = 0; // ile razy dodany do kolejki
|
||||||
// bool bIsHistory;
|
|
||||||
TEvent *evNext = nullptr; // następny w kolejce
|
TEvent *evNext = nullptr; // następny w kolejce
|
||||||
TEvent *evNext2 = nullptr;
|
|
||||||
TEventType Type = tp_Unknown;
|
TEventType Type = tp_Unknown;
|
||||||
double fStartTime = 0.0;
|
double fStartTime = 0.0;
|
||||||
double fDelay = 0.0;
|
double fDelay = 0.0;
|
||||||
@@ -100,19 +101,79 @@ class TEvent // zmienne: ev*
|
|||||||
std::string asNodeName; // McZapkie-100302 - dodalem zeby zapamietac nazwe toru
|
std::string asNodeName; // McZapkie-100302 - dodalem zeby zapamietac nazwe toru
|
||||||
TEvent *evJoined = nullptr; // kolejny event z tą samą nazwą - od wersji 378
|
TEvent *evJoined = nullptr; // kolejny event z tą samą nazwą - od wersji 378
|
||||||
double fRandomDelay = 0.0; // zakres dodatkowego opóźnienia // standardowo nie będzie dodatkowego losowego opóźnienia
|
double fRandomDelay = 0.0; // zakres dodatkowego opóźnienia // standardowo nie będzie dodatkowego losowego opóźnienia
|
||||||
public: // metody
|
public:
|
||||||
|
// metody
|
||||||
TEvent(std::string const &m = "");
|
TEvent(std::string const &m = "");
|
||||||
~TEvent();
|
~TEvent();
|
||||||
void Init();
|
void Load(cParser *parser, Math3D::vector3 const &org);
|
||||||
void Load(cParser *parser, vector3 *org);
|
|
||||||
static void AddToQuery( TEvent *Event, TEvent *&Start );
|
static void AddToQuery( TEvent *Event, TEvent *&Start );
|
||||||
std::string CommandGet();
|
std::string CommandGet();
|
||||||
TCommandType Command();
|
TCommandType Command();
|
||||||
double ValueGet(int n);
|
double ValueGet(int n);
|
||||||
vector3 PositionGet() const;
|
glm::dvec3 PositionGet() const;
|
||||||
bool StopCommand();
|
bool StopCommand();
|
||||||
void StopCommandSent();
|
void StopCommandSent();
|
||||||
void Append(TEvent *e);
|
void Append(TEvent *e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class event_manager {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// destructor
|
||||||
|
~event_manager();
|
||||||
|
// methods
|
||||||
|
// adds specified event launcher to the list of global launchers
|
||||||
|
void
|
||||||
|
queue( TEventLauncher *Launcher );
|
||||||
|
// legacy method, updates event queues
|
||||||
|
void
|
||||||
|
update();
|
||||||
|
// adds provided event to the collection. returns: true on success
|
||||||
|
// 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 );
|
||||||
|
// legacy method, inserts specified event in the event query
|
||||||
|
bool
|
||||||
|
AddToQuery( TEvent *Event, TDynamicObject *Owner );
|
||||||
|
// legacy method, executes queued events
|
||||||
|
bool
|
||||||
|
CheckQuery();
|
||||||
|
// legacy method, initializes events after deserialization from scenario file
|
||||||
|
void
|
||||||
|
InitEvents();
|
||||||
|
// legacy method, initializes event launchers after deserialization from scenario file
|
||||||
|
void
|
||||||
|
InitLaunchers();
|
||||||
|
|
||||||
|
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
|
||||||
|
bool
|
||||||
|
EventConditon( TEvent *Event );
|
||||||
|
|
||||||
|
// members
|
||||||
|
event_sequence m_events;
|
||||||
|
/*
|
||||||
|
// NOTE: disabled until event class refactoring
|
||||||
|
event_sequence m_eventqueue;
|
||||||
|
*/
|
||||||
|
// 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 "Classes.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
|
||||||
typedef enum
|
enum TGaugeType {
|
||||||
{ // typ ruchu
|
// typ ruchu
|
||||||
gt_Unknown, // na razie nie znany
|
gt_Unknown, // na razie nie znany
|
||||||
gt_Rotate, // obrót
|
gt_Rotate, // obrót
|
||||||
gt_Move, // przesunięcie równoległe
|
gt_Move, // przesunięcie równoległe
|
||||||
gt_Wiper, // obrót trzech kolejnych submodeli o ten sam kąt (np. wycieraczka, drzwi
|
gt_Wiper, // obrót trzech kolejnych submodeli o ten sam kąt (np. wycieraczka, drzwi harmonijkowe)
|
||||||
// harmonijkowe)
|
|
||||||
gt_Digital // licznik cyfrowy, np. kilometrów
|
gt_Digital // licznik cyfrowy, np. kilometrów
|
||||||
} TGaugeType;
|
};
|
||||||
|
|
||||||
// animowany wskaźnik, mogący przyjmować wiele stanów pośrednich
|
// animowany wskaźnik, mogący przyjmować wiele stanów pośrednich
|
||||||
class TGauge {
|
class TGauge {
|
||||||
|
|||||||
55
Globals.cpp
55
Globals.cpp
@@ -12,22 +12,17 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "usefull.h"
|
|
||||||
//#include "Mover.h"
|
|
||||||
#include "Console.h"
|
|
||||||
#include "Driver.h"
|
|
||||||
#include "Logs.h"
|
|
||||||
#include "PyInt.h"
|
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "parser.h"
|
#include "simulation.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "PyInt.h"
|
||||||
|
|
||||||
// namespace Global {
|
// namespace Global {
|
||||||
|
|
||||||
// parametry do użytku wewnętrznego
|
// parametry do użytku wewnętrznego
|
||||||
// double Global::tSinceStart=0;
|
|
||||||
TGround *Global::pGround = NULL;
|
|
||||||
std::string Global::AppName{ "EU07" };
|
std::string Global::AppName{ "EU07" };
|
||||||
std::string Global::asCurrentSceneryPath = "scenery/";
|
std::string Global::asCurrentSceneryPath = "scenery/";
|
||||||
std::string Global::asCurrentTexturePath = std::string(szTexturePath);
|
std::string Global::asCurrentTexturePath = std::string(szTexturePath);
|
||||||
@@ -75,11 +70,14 @@ GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
|
|||||||
double Global::fFogStart = 1700;
|
double Global::fFogStart = 1700;
|
||||||
double Global::fFogEnd = 2000;
|
double Global::fFogEnd = 2000;
|
||||||
float Global::Overcast { 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
float Global::Overcast { 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
||||||
int Global::DynamicLightCount = 7;
|
std::string Global::Season; // season of the year, based on simulation date
|
||||||
bool Global::ScaleSpecularValues = false;
|
|
||||||
float Global::BaseDrawRange { 2500.f };
|
float Global::BaseDrawRange { 2500.f };
|
||||||
bool Global::RenderShadows { false };
|
opengl_light Global::DayLight;
|
||||||
|
int Global::DynamicLightCount { 3 };
|
||||||
|
bool Global::ScaleSpecularValues { true };
|
||||||
bool Global::BasicRenderer { false };
|
bool Global::BasicRenderer { false };
|
||||||
|
bool Global::RenderShadows { true };
|
||||||
Global::shadowtune_t Global::shadowtune = { 2048, 250.f, 250.f, 500.f };
|
Global::shadowtune_t Global::shadowtune = { 2048, 250.f, 250.f, 500.f };
|
||||||
bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki
|
bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki
|
||||||
bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach
|
bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach
|
||||||
@@ -118,7 +116,7 @@ bool Global::bLiveTraction = true;
|
|||||||
float Global::AnisotropicFiltering = 8.0f; // requested level of anisotropic filtering. TODO: move it to renderer object
|
float Global::AnisotropicFiltering = 8.0f; // requested level of anisotropic filtering. TODO: move it to renderer object
|
||||||
std::string Global::LastGLError;
|
std::string Global::LastGLError;
|
||||||
GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury
|
GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury
|
||||||
bool Global::bSmoothTraction = false; // wygładzanie drutów starym sposobem
|
bool Global::bSmoothTraction { true }; // wygładzanie drutów starym sposobem
|
||||||
float Global::SplineFidelity { 1.f }; // determines segment size during conversion of splines to geometry
|
float Global::SplineFidelity { 1.f }; // determines segment size during conversion of splines to geometry
|
||||||
std::string Global::szDefaultExt = Global::szTexturesDDS; // domyślnie od DDS
|
std::string Global::szDefaultExt = Global::szTexturesDDS; // domyślnie od DDS
|
||||||
int Global::iMultisampling = 2; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
int Global::iMultisampling = 2; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
||||||
@@ -172,7 +170,6 @@ Global::uart_conf_t Global::uart_conf;
|
|||||||
//randomizacja
|
//randomizacja
|
||||||
std::mt19937 Global::random_engine = std::mt19937(std::time(NULL));
|
std::mt19937 Global::random_engine = std::mt19937(std::time(NULL));
|
||||||
|
|
||||||
opengl_light Global::DayLight;
|
|
||||||
Global::soundmode_t Global::soundpitchmode = Global::linear;
|
Global::soundmode_t Global::soundpitchmode = Global::linear;
|
||||||
Global::soundmode_t Global::soundgainmode = Global::linear;
|
Global::soundmode_t Global::soundgainmode = Global::linear;
|
||||||
Global::soundstopmode_t Global::soundstopmode = Global::queue;
|
Global::soundstopmode_t Global::soundstopmode = Global::queue;
|
||||||
@@ -181,19 +178,6 @@ Global::soundstopmode_t Global::soundstopmode = Global::queue;
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
std::string Global::GetNextSymbol()
|
|
||||||
{ // pobranie tokenu z aktualnego parsera
|
|
||||||
|
|
||||||
std::string token;
|
|
||||||
if (pParser != nullptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
pParser->getTokens();
|
|
||||||
*pParser >> token;
|
|
||||||
};
|
|
||||||
return token;
|
|
||||||
};
|
|
||||||
|
|
||||||
void Global::LoadIniFile(std::string asFileName)
|
void Global::LoadIniFile(std::string asFileName)
|
||||||
{
|
{
|
||||||
FreeCameraInit.resize( 10 );
|
FreeCameraInit.resize( 10 );
|
||||||
@@ -449,6 +433,7 @@ void Global::ConfigParse(cParser &Parser)
|
|||||||
std::tm *localtime = std::localtime(&timenow);
|
std::tm *localtime = std::localtime(&timenow);
|
||||||
Global::fMoveLight = localtime->tm_yday + 1; // numer bieżącego dnia w roku
|
Global::fMoveLight = localtime->tm_yday + 1; // numer bieżącego dnia w roku
|
||||||
}
|
}
|
||||||
|
Global::pWorld->compute_season( Global::fMoveLight );
|
||||||
}
|
}
|
||||||
else if( token == "dynamiclights" ) {
|
else if( token == "dynamiclights" ) {
|
||||||
// number of dynamic lights in the scene
|
// number of dynamic lights in the scene
|
||||||
@@ -949,20 +934,6 @@ void Global::TrainDelete(TDynamicObject *d)
|
|||||||
pWorld->TrainDelete(d);
|
pWorld->TrainDelete(d);
|
||||||
};
|
};
|
||||||
|
|
||||||
TDynamicObject *Global::DynamicNearest()
|
|
||||||
{ // ustalenie pojazdu najbliższego kamerze
|
|
||||||
return pGround->DynamicNearest(pCamera->Pos);
|
|
||||||
};
|
|
||||||
|
|
||||||
TDynamicObject *Global::CouplerNearest()
|
|
||||||
{ // ustalenie pojazdu najbliższego kamerze
|
|
||||||
return pGround->CouplerNearest(pCamera->Pos);
|
|
||||||
};
|
|
||||||
|
|
||||||
bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
|
|
||||||
{
|
|
||||||
return pGround->AddToQuery(event, who);
|
|
||||||
};
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TTranscripts::TTranscripts()
|
TTranscripts::TTranscripts()
|
||||||
|
|||||||
54
Globals.h
54
Globals.h
@@ -150,16 +150,27 @@ private:
|
|||||||
void Update();
|
void Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Global
|
class Global {
|
||||||
{
|
|
||||||
private:
|
|
||||||
public:
|
public:
|
||||||
|
// methods
|
||||||
|
static void LoadIniFile(std::string asFileName);
|
||||||
|
static void ConfigParse( cParser &parser );
|
||||||
|
static void InitKeys();
|
||||||
|
inline static Math3D::vector3 GetCameraPosition() { return pCameraPosition; };
|
||||||
|
static void SetCameraPosition(Math3D::vector3 pNewCameraPosition);
|
||||||
|
static void SetCameraRotation(double Yaw);
|
||||||
|
static void TrainDelete(TDynamicObject *d);
|
||||||
|
static bool DoEvents();
|
||||||
|
static std::string Bezogonkow(std::string str, bool _ = false);
|
||||||
|
static double Min0RSpeed(double vel1, double vel2);
|
||||||
|
|
||||||
|
// members
|
||||||
static int Keys[MaxKeys];
|
static int Keys[MaxKeys];
|
||||||
static bool RealisticControlMode; // controls ability to steer the vehicle from outside views
|
static bool RealisticControlMode; // controls ability to steer the vehicle from outside views
|
||||||
static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie
|
static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie
|
||||||
static Math3D::vector3 DebugCameraPosition; // pozycja kamery w świecie
|
static Math3D::vector3 DebugCameraPosition; // pozycja kamery w świecie
|
||||||
static double
|
static double pCameraRotation; // kierunek bezwzględny kamery w świecie: 0=północ, 90°=zachód (-azymut)
|
||||||
pCameraRotation; // kierunek bezwzględny kamery w świecie: 0=północ, 90°=zachód (-azymut)
|
|
||||||
static double pCameraRotationDeg; // w stopniach, dla animacji billboard
|
static double pCameraRotationDeg; // w stopniach, dla animacji billboard
|
||||||
static std::vector<Math3D::vector3> FreeCameraInit; // pozycje kamery
|
static std::vector<Math3D::vector3> FreeCameraInit; // pozycje kamery
|
||||||
static std::vector<Math3D::vector3> FreeCameraInitAngle;
|
static std::vector<Math3D::vector3> FreeCameraInitAngle;
|
||||||
@@ -179,27 +190,21 @@ class Global
|
|||||||
static bool bLiveTraction;
|
static bool bLiveTraction;
|
||||||
static float fMouseXScale;
|
static float fMouseXScale;
|
||||||
static float fMouseYScale;
|
static float fMouseYScale;
|
||||||
static double fFogStart;
|
|
||||||
static double fFogEnd;
|
|
||||||
static TGround *pGround;
|
|
||||||
static std::string szDefaultExt;
|
static std::string szDefaultExt;
|
||||||
static std::string SceneryFile;
|
static std::string SceneryFile;
|
||||||
static std::string AppName;
|
static std::string AppName;
|
||||||
static std::string asCurrentSceneryPath;
|
static std::string asCurrentSceneryPath;
|
||||||
static std::string asCurrentTexturePath;
|
static std::string asCurrentTexturePath;
|
||||||
static std::string asCurrentDynamicPath;
|
static std::string asCurrentDynamicPath;
|
||||||
// McZapkie-170602: zewnetrzna definicja pojazdu uzytkownika
|
|
||||||
static std::string asHumanCtrlVehicle;
|
|
||||||
static void LoadIniFile(std::string asFileName);
|
|
||||||
static void InitKeys();
|
|
||||||
inline static Math3D::vector3 GetCameraPosition() { return pCameraPosition; };
|
|
||||||
static void SetCameraPosition(Math3D::vector3 pNewCameraPosition);
|
|
||||||
static void SetCameraRotation(double Yaw);
|
|
||||||
static int iWriteLogEnabled; // maska bitowa: 1-zapis do pliku, 2-okienko
|
static int iWriteLogEnabled; // maska bitowa: 1-zapis do pliku, 2-okienko
|
||||||
static bool MultipleLogs;
|
static bool MultipleLogs;
|
||||||
// McZapkie-221002: definicja swiatla dziennego
|
// McZapkie-170602: zewnetrzna definicja pojazdu uzytkownika
|
||||||
static GLfloat FogColor[];
|
static std::string asHumanCtrlVehicle;
|
||||||
|
// world environment
|
||||||
static float Overcast;
|
static float Overcast;
|
||||||
|
static double fFogStart;
|
||||||
|
static double fFogEnd;
|
||||||
|
static std::string Season; // season of the year, based on simulation date
|
||||||
|
|
||||||
// TODO: put these things in the renderer
|
// TODO: put these things in the renderer
|
||||||
static float BaseDrawRange;
|
static float BaseDrawRange;
|
||||||
@@ -221,6 +226,9 @@ class Global
|
|||||||
static float FieldOfView; // vertical field of view for the camera. TODO: move it to the renderer
|
static float FieldOfView; // vertical field of view for the camera. TODO: move it to the renderer
|
||||||
static GLint iMaxTextureSize; // maksymalny rozmiar tekstury
|
static GLint iMaxTextureSize; // maksymalny rozmiar tekstury
|
||||||
static int iMultisampling; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
static int iMultisampling; // tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
|
||||||
|
static bool bSmoothTraction; // wygładzanie drutów
|
||||||
|
static float SplineFidelity; // determines segment size during conversion of splines to geometry
|
||||||
|
static GLfloat FogColor[];
|
||||||
|
|
||||||
static bool FullPhysics; // full calculations performed for each simulation step
|
static bool FullPhysics; // full calculations performed for each simulation step
|
||||||
static int iSlowMotion;
|
static int iSlowMotion;
|
||||||
@@ -247,8 +255,6 @@ class Global
|
|||||||
static int iScreenMode[12]; // numer ekranu wyświetlacza tekstowego
|
static int iScreenMode[12]; // numer ekranu wyświetlacza tekstowego
|
||||||
static double fMoveLight; // numer dnia w roku albo -1
|
static double fMoveLight; // numer dnia w roku albo -1
|
||||||
static bool FakeLight; // toggle between fixed and dynamic daylight
|
static bool FakeLight; // toggle between fixed and dynamic daylight
|
||||||
static bool bSmoothTraction; // wygładzanie drutów
|
|
||||||
static float SplineFidelity; // determines segment size during conversion of splines to geometry
|
|
||||||
static double fTimeSpeed; // przyspieszenie czasu, zmienna do testów
|
static double fTimeSpeed; // przyspieszenie czasu, zmienna do testów
|
||||||
static double fTimeAngleDeg; // godzina w postaci kąta
|
static double fTimeAngleDeg; // godzina w postaci kąta
|
||||||
static float fClockAngleDeg[6]; // kąty obrotu cylindrów dla zegara cyfrowego
|
static float fClockAngleDeg[6]; // kąty obrotu cylindrów dla zegara cyfrowego
|
||||||
@@ -324,16 +330,6 @@ class Global
|
|||||||
};
|
};
|
||||||
static uart_conf_t uart_conf;
|
static uart_conf_t uart_conf;
|
||||||
|
|
||||||
// metody
|
|
||||||
static void TrainDelete(TDynamicObject *d);
|
|
||||||
static void ConfigParse(cParser &parser);
|
|
||||||
static std::string GetNextSymbol();
|
|
||||||
static TDynamicObject * DynamicNearest();
|
|
||||||
static TDynamicObject * CouplerNearest();
|
|
||||||
static bool AddToQuery(TEvent *event, TDynamicObject *who);
|
|
||||||
static std::string Bezogonkow(std::string str, bool _ = false);
|
|
||||||
static double Min0RSpeed(double vel1, double vel2);
|
|
||||||
|
|
||||||
static opengl_light DayLight;
|
static opengl_light DayLight;
|
||||||
|
|
||||||
enum soundmode_t
|
enum soundmode_t
|
||||||
|
|||||||
4360
Ground.cpp
4360
Ground.cpp
File diff suppressed because it is too large
Load Diff
352
Ground.h
352
Ground.h
@@ -1,352 +0,0 @@
|
|||||||
/*
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "GL/glew.h"
|
|
||||||
#include "openglgeometrybank.h"
|
|
||||||
#include "VBO.h"
|
|
||||||
#include "Classes.h"
|
|
||||||
#include "ResourceManager.h"
|
|
||||||
#include "material.h"
|
|
||||||
#include "dumb3d.h"
|
|
||||||
#include "Float3d.h"
|
|
||||||
#include "Names.h"
|
|
||||||
#include "lightarray.h"
|
|
||||||
#include "lua.h"
|
|
||||||
|
|
||||||
typedef int TGroundNodeType;
|
|
||||||
// Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie
|
|
||||||
const int TP_MODEL = 10;
|
|
||||||
/*
|
|
||||||
const int TP_MESH = 11; // Ra: specjalny obiekt grupujący siatki dla tekstury
|
|
||||||
const int TP_DUMMYTRACK = 12; // Ra: zdublowanie obiektu toru dla rozdzielenia tekstur
|
|
||||||
*/
|
|
||||||
const int TP_TERRAIN = 13; // Ra: specjalny model dla terenu
|
|
||||||
const int TP_DYNAMIC = 14;
|
|
||||||
const int TP_SOUND = 15;
|
|
||||||
const int TP_TRACK = 16;
|
|
||||||
/*
|
|
||||||
const int TP_GEOMETRY=17;
|
|
||||||
*/
|
|
||||||
const int TP_MEMCELL = 18;
|
|
||||||
const int TP_EVLAUNCH = 19; // MC
|
|
||||||
const int TP_TRACTION = 20;
|
|
||||||
const int TP_TRACTIONPOWERSOURCE = 21; // MC
|
|
||||||
/*
|
|
||||||
const int TP_ISOLATED=22; //Ra
|
|
||||||
*/
|
|
||||||
const int TP_SUBMODEL = 22; // Ra: submodele terenu
|
|
||||||
const int TP_LAST = 25; // rozmiar tablicy
|
|
||||||
|
|
||||||
struct DaneRozkaz
|
|
||||||
{ // struktura komunikacji z EU07.EXE
|
|
||||||
int iSygn; // sygnatura 'EU07'
|
|
||||||
int iComm; // rozkaz/status (kod ramki)
|
|
||||||
union
|
|
||||||
{
|
|
||||||
float fPar[62];
|
|
||||||
int iPar[62];
|
|
||||||
char cString[248]; // upakowane stringi
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DaneRozkaz2
|
|
||||||
{ // struktura komunikacji z EU07.EXE
|
|
||||||
int iSygn; // sygnatura 'EU07'
|
|
||||||
int iComm; // rozkaz/status (kod ramki)
|
|
||||||
union
|
|
||||||
{
|
|
||||||
float fPar[496];
|
|
||||||
int iPar[496];
|
|
||||||
char cString[1984]; // upakowane stringi
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TGroundVertex
|
|
||||||
{
|
|
||||||
glm::dvec3 position;
|
|
||||||
glm::vec3 normal;
|
|
||||||
glm::vec2 texture;
|
|
||||||
|
|
||||||
void HalfSet(const TGroundVertex &v1, const TGroundVertex &v2)
|
|
||||||
{ // wyliczenie współrzędnych i mapowania punktu na środku odcinka v1<->v2
|
|
||||||
interpolate_( v1, v2, 0.5 );
|
|
||||||
}
|
|
||||||
void SetByX(const TGroundVertex &v1, const TGroundVertex &v2, double x)
|
|
||||||
{ // wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
|
|
||||||
interpolate_( v1, v2, ( x - v1.position.x ) / ( v2.position.x - v1.position.x ) );
|
|
||||||
}
|
|
||||||
void SetByZ(const TGroundVertex &v1, const TGroundVertex &v2, double z)
|
|
||||||
{ // wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
|
|
||||||
interpolate_( v1, v2, ( z - v1.position.z ) / ( v2.position.z - v1.position.z ) );
|
|
||||||
}
|
|
||||||
void interpolate_( const TGroundVertex &v1, const TGroundVertex &v2, double factor ) {
|
|
||||||
position = interpolate( v1.position, v2.position, factor );
|
|
||||||
normal = interpolate( v1.normal, v2.normal, static_cast<float>( factor ) );
|
|
||||||
texture = interpolate( v1.texture, v2.texture, static_cast<float>( factor ) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node
|
|
||||||
struct piece_node {
|
|
||||||
std::vector<TGroundVertex> vertices;
|
|
||||||
geometry_handle geometry { 0,0 }; // geometry prepared for drawing
|
|
||||||
};
|
|
||||||
|
|
||||||
// obiekt scenerii
|
|
||||||
class TGroundNode {
|
|
||||||
|
|
||||||
friend class opengl_renderer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TGroundNode *nNext; // lista wszystkich w scenerii, ostatni na początku
|
|
||||||
TGroundNode *nNext2; // lista obiektów w sektorze
|
|
||||||
TGroundNode *nNext3; // lista obiektów renderowanych we wspólnym cyklu
|
|
||||||
std::string asName; // nazwa (nie zawsze ma znaczenie)
|
|
||||||
TGroundNodeType iType; // typ obiektu
|
|
||||||
union
|
|
||||||
{ // Ra: wskażniki zależne od typu - zrobić klasy dziedziczone zamiast
|
|
||||||
void *Pointer; // do przypisywania NULL
|
|
||||||
TSubModel *smTerrain; // modele terenu (kwadratow kilometrowych)
|
|
||||||
TAnimModel *Model; // model z animacjami
|
|
||||||
TDynamicObject *DynamicObject; // pojazd
|
|
||||||
piece_node *Piece; // non-instanced piece of geometry
|
|
||||||
TTrack *pTrack; // trajektoria ruchu
|
|
||||||
TMemCell *MemCell; // komórka pamięci
|
|
||||||
TEventLauncher *EvLaunch; // wyzwalacz zdarzeń
|
|
||||||
TTraction *hvTraction; // drut zasilający
|
|
||||||
TTractionPowerSource *psTractionPowerSource; // zasilanie drutu (zaniedbane w sceneriach)
|
|
||||||
sound *tsStaticSound; // dźwięk przestrzenny
|
|
||||||
TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
|
|
||||||
};
|
|
||||||
Math3D::vector3 pCenter; // współrzędne środka do przydzielenia sektora
|
|
||||||
float m_radius { 0.0f }; // bounding radius of geometry stored in the node. TODO: reuse bounding_area struct for radius and center
|
|
||||||
glm::dvec3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
|
|
||||||
// visualization-related data
|
|
||||||
// TODO: wrap these in a struct, when cleaning objects up
|
|
||||||
double fSquareMinRadius; // kwadrat widoczności od
|
|
||||||
double fSquareRadius; // kwadrat widoczności do
|
|
||||||
union
|
|
||||||
{
|
|
||||||
int iNumVerts; // dla trójkątów
|
|
||||||
int iNumPts; // dla linii
|
|
||||||
int iCount; // dla terenu
|
|
||||||
};
|
|
||||||
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
|
|
||||||
material_handle m_material; // główna (jedna) tekstura obiektu
|
|
||||||
glm::vec3
|
|
||||||
Ambient{ 1.0f, 1.0f, 1.0f },
|
|
||||||
Diffuse{ 1.0f, 1.0f, 1.0f },
|
|
||||||
Specular{ 1.0f, 1.0f, 1.0f }; // oświetlenie
|
|
||||||
double fLineThickness; // McZapkie-120702: grubosc linii
|
|
||||||
bool bVisible;
|
|
||||||
|
|
||||||
TGroundNode();
|
|
||||||
TGroundNode(TGroundNodeType t);
|
|
||||||
~TGroundNode();
|
|
||||||
|
|
||||||
void InitNormals();
|
|
||||||
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bounding_area {
|
|
||||||
|
|
||||||
glm::vec3 center; // mid point of the rectangle
|
|
||||||
float radius { 0.0f }; // radius of the bounding sphere
|
|
||||||
};
|
|
||||||
|
|
||||||
class TSubRect : /*public Resource,*/ public CMesh
|
|
||||||
{ // sektor składowy kwadratu kilometrowego
|
|
||||||
public:
|
|
||||||
bounding_area m_area;
|
|
||||||
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
|
||||||
int iTracks = 0; // ilość torów w (tTracks)
|
|
||||||
TTrack **tTracks = nullptr; // tory do renderowania pojazdów
|
|
||||||
protected:
|
|
||||||
TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji
|
|
||||||
public:
|
|
||||||
TGroundNode *nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2)
|
|
||||||
TGroundNode *nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3)
|
|
||||||
TGroundNode *nRenderRect = nullptr; // z poziomu sektora - nieprzezroczyste (nNext3)
|
|
||||||
TGroundNode *nRenderRectAlpha = nullptr; // z poziomu sektora - przezroczyste (nNext3)
|
|
||||||
TGroundNode *nRenderWires = nullptr; // z poziomu sektora - druty i inne linie (nNext3)
|
|
||||||
TGroundNode *nRender = nullptr; // indywidualnie - nieprzezroczyste (nNext3)
|
|
||||||
TGroundNode *nRenderMixed = nullptr; // indywidualnie - nieprzezroczyste i przezroczyste (nNext3)
|
|
||||||
TGroundNode *nRenderAlpha = nullptr; // indywidualnie - przezroczyste (nNext3)
|
|
||||||
#ifdef EU07_SCENERY_EDITOR
|
|
||||||
std::deque< TGroundNode* > m_memcells; // collection of memcells present in the sector
|
|
||||||
#endif
|
|
||||||
int iNodeCount = 0; // licznik obiektów, do pomijania pustych sektorów
|
|
||||||
public:
|
|
||||||
void LoadNodes(); // utworzenie VBO sektora
|
|
||||||
public:
|
|
||||||
virtual ~TSubRect();
|
|
||||||
virtual void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
|
||||||
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
|
|
||||||
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
|
|
||||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
|
|
||||||
bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
|
|
||||||
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji torów
|
|
||||||
void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ra: trzeba sprawdzić wydajność siatki
|
|
||||||
const int iNumSubRects = 5; // na ile dzielimy kilometr
|
|
||||||
const int iNumRects = 500;
|
|
||||||
const int iTotalNumSubRects = iNumRects * iNumSubRects;
|
|
||||||
const double fHalfTotalNumSubRects = iTotalNumSubRects / 2.0;
|
|
||||||
const double fSubRectSize = 1000.0 / iNumSubRects;
|
|
||||||
const double fRectSize = fSubRectSize * iNumSubRects;
|
|
||||||
|
|
||||||
class TGroundRect : public TSubRect
|
|
||||||
{ // kwadrat kilometrowy
|
|
||||||
// obiekty o niewielkiej ilości wierzchołków będą renderowane stąd
|
|
||||||
// Ra: 2012-02 doszły submodele terenu
|
|
||||||
friend class opengl_renderer;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TSubRect *pSubRects { nullptr };
|
|
||||||
|
|
||||||
void Init();
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~TGroundRect();
|
|
||||||
// pobranie wskaźnika do małego kwadratu, utworzenie jeśli trzeba
|
|
||||||
TSubRect * SafeGetSubRect(int iCol, int iRow) {
|
|
||||||
if( !pSubRects ) {
|
|
||||||
// utworzenie małych kwadratów
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
return pSubRects + iRow * iNumSubRects + iCol; // zwrócenie właściwego
|
|
||||||
};
|
|
||||||
// pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
|
|
||||||
TSubRect *FastGetSubRect(int iCol, int iRow) const {
|
|
||||||
return (
|
|
||||||
pSubRects ?
|
|
||||||
pSubRects + iRow * iNumSubRects + iCol :
|
|
||||||
nullptr); };
|
|
||||||
void NodeAdd( TGroundNode *Node ); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
|
||||||
// compares two provided nodes, returns true if their content can be merged
|
|
||||||
bool mergeable( TGroundNode const &Left, TGroundNode const &Right );
|
|
||||||
// optymalizacja obiektów w sektorach
|
|
||||||
void Optimize() {
|
|
||||||
if( pSubRects ) {
|
|
||||||
for( int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i ) {
|
|
||||||
// optymalizacja obiektów w sektorach
|
|
||||||
pSubRects[ i ].Sort(); } } };
|
|
||||||
|
|
||||||
TGroundNode *nTerrain { nullptr }; // model terenu z E3D - użyć nRootMesh?
|
|
||||||
};
|
|
||||||
|
|
||||||
class TGround
|
|
||||||
{
|
|
||||||
friend class opengl_renderer;
|
|
||||||
|
|
||||||
TGroundRect Rects[ iNumRects ][ iNumRects ]; // mapa kwadratów kilometrowych
|
|
||||||
TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe)
|
|
||||||
TGroundNode *nRootDynamic = nullptr; // lista pojazdów
|
|
||||||
TGroundNode *nRootOfType[ TP_LAST ]; // tablica grupująca obiekty, przyspiesza szukanie
|
|
||||||
TEvent *RootEvent = nullptr; // lista zdarzeń
|
|
||||||
TEvent *QueryRootEvent = nullptr,
|
|
||||||
*tmpEvent = nullptr;
|
|
||||||
typedef std::unordered_map<std::string, TEvent *> event_map;
|
|
||||||
event_map m_eventmap;
|
|
||||||
TNames<TGroundNode *> m_trackmap;
|
|
||||||
light_array m_lights; // collection of dynamic light sources present in the scene
|
|
||||||
lua m_lua;
|
|
||||||
|
|
||||||
vector3 pOrigin;
|
|
||||||
vector3 aRotate;
|
|
||||||
bool bInitDone = false;
|
|
||||||
|
|
||||||
private: // metody prywatne
|
|
||||||
bool EventConditon(TEvent *e);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool bDynamicRemove = false; // czy uruchomić procedurę usuwania pojazdów
|
|
||||||
|
|
||||||
TGround();
|
|
||||||
~TGround();
|
|
||||||
void Free();
|
|
||||||
bool Init( std::string File );
|
|
||||||
void FirstInit();
|
|
||||||
void InitTracks();
|
|
||||||
void InitTraction();
|
|
||||||
bool InitEvents();
|
|
||||||
bool InitLaunchers();
|
|
||||||
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
|
|
||||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TGroundNode *Exclude);
|
|
||||||
TTraction * TractionNearestFind(glm::dvec3 &p, int dir, TGroundNode *n);
|
|
||||||
TGroundNode * AddGroundNode(cParser *parser);
|
|
||||||
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
|
|
||||||
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS
|
|
||||||
void Update_Lights(); // updates scene lights array
|
|
||||||
void Update_Hidden(); // updates invisible elements of the scene
|
|
||||||
bool AddToQuery(TEvent *Event, TDynamicObject *Node);
|
|
||||||
bool GetTraction(TDynamicObject *model);
|
|
||||||
bool CheckQuery();
|
|
||||||
TGroundNode * DynamicFindAny(std::string const &Name);
|
|
||||||
TGroundNode * DynamicFind(std::string const &Name);
|
|
||||||
void DynamicList(bool all = false);
|
|
||||||
TGroundNode * FindGroundNode(std::string asNameToFind, TGroundNodeType iNodeType);
|
|
||||||
TGroundRect * GetRect( double x, double z );
|
|
||||||
TSubRect * GetSubRect( int iCol, int iRow );
|
|
||||||
inline
|
|
||||||
TSubRect * GetSubRect(double x, double z) {
|
|
||||||
return GetSubRect(GetColFromX(x), GetRowFromZ(z)); };
|
|
||||||
TSubRect * FastGetSubRect( int iCol, int iRow );
|
|
||||||
inline
|
|
||||||
TSubRect * FastGetSubRect( double x, double z ) {
|
|
||||||
return FastGetSubRect( GetColFromX( x ), GetRowFromZ( z ) ); };
|
|
||||||
inline
|
|
||||||
int GetRowFromZ(double z) {
|
|
||||||
return (int)(z / fSubRectSize + fHalfTotalNumSubRects); };
|
|
||||||
inline
|
|
||||||
int GetColFromX(double x) {
|
|
||||||
return (int)(x / fSubRectSize + fHalfTotalNumSubRects); };
|
|
||||||
TEvent * FindEvent(const std::string &asEventName);
|
|
||||||
TEvent * FindEventScan(const std::string &asEventName);
|
|
||||||
void TrackJoin(TGroundNode *Current);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// convert tp_terrain model to a series of triangle nodes
|
|
||||||
void convert_terrain( TGroundNode const *Terrain );
|
|
||||||
void convert_terrain( TSubModel const *Submodel );
|
|
||||||
void RaTriangleDivider(TGroundNode *node);
|
|
||||||
#ifdef _WIN32
|
|
||||||
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
void WyslijEvent(const std::string &e, const std::string &d);
|
|
||||||
void WyslijString(const std::string &t, int n);
|
|
||||||
void WyslijWolny(const std::string &t);
|
|
||||||
void WyslijNamiary(TGroundNode *t);
|
|
||||||
void WyslijParam(int nr, int fl);
|
|
||||||
void WyslijUszkodzenia(const std::string &t, char fl);
|
|
||||||
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
|
||||||
void RadioStop(vector3 pPosition);
|
|
||||||
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0,
|
|
||||||
bool mech = false);
|
|
||||||
TDynamicObject * CouplerNearest(vector3 pPosition, double distance = 20.0,
|
|
||||||
bool mech = false);
|
|
||||||
void DynamicRemove(TDynamicObject *dyn);
|
|
||||||
void TerrainRead(std::string const &f);
|
|
||||||
void TerrainWrite();
|
|
||||||
void TrackBusyList();
|
|
||||||
void IsolatedBusyList();
|
|
||||||
void IsolatedBusy(const std::string t);
|
|
||||||
void Silence(vector3 gdzie);
|
|
||||||
|
|
||||||
void add_event(TEvent *event);
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
@@ -706,6 +706,7 @@ public:
|
|||||||
headlight_upper = 0x04,
|
headlight_upper = 0x04,
|
||||||
headlight_right = 0x10,
|
headlight_right = 0x10,
|
||||||
redmarker_right = 0x20,
|
redmarker_right = 0x20,
|
||||||
|
rearendsignals = 0x40
|
||||||
};
|
};
|
||||||
int ScndInMain{ 0 }; /*zaleznosc bocznika od nastawnika*/
|
int ScndInMain{ 0 }; /*zaleznosc bocznika od nastawnika*/
|
||||||
bool MBrake = false; /*Czy jest hamulec reczny*/
|
bool MBrake = false; /*Czy jest hamulec reczny*/
|
||||||
@@ -778,6 +779,7 @@ public:
|
|||||||
double Ftmax = 0.0;
|
double Ftmax = 0.0;
|
||||||
/*- dla lokomotyw z silnikami indukcyjnymi -*/
|
/*- dla lokomotyw z silnikami indukcyjnymi -*/
|
||||||
double eimc[26];
|
double eimc[26];
|
||||||
|
bool EIMCLogForce; //
|
||||||
static std::vector<std::string> const eimc_labels;
|
static std::vector<std::string> const eimc_labels;
|
||||||
/*-dla wagonow*/
|
/*-dla wagonow*/
|
||||||
double MaxLoad = 0.0; /*masa w T lub ilosc w sztukach - ladownosc*/
|
double MaxLoad = 0.0; /*masa w T lub ilosc w sztukach - ladownosc*/
|
||||||
@@ -820,6 +822,7 @@ public:
|
|||||||
double AccN = 0.0; //przyspieszenie normalne w [m/s^2]
|
double AccN = 0.0; //przyspieszenie normalne w [m/s^2]
|
||||||
double AccV = 0.0;
|
double AccV = 0.0;
|
||||||
double nrot = 0.0;
|
double nrot = 0.0;
|
||||||
|
double WheelFlat = 0.0;
|
||||||
/*! rotacja kol [obr/s]*/
|
/*! rotacja kol [obr/s]*/
|
||||||
double EnginePower = 0.0; /*! chwilowa moc silnikow*/
|
double EnginePower = 0.0; /*! chwilowa moc silnikow*/
|
||||||
double dL = 0.0; double Fb = 0.0; double Ff = 0.0; /*przesuniecie, sila hamowania i tarcia*/
|
double dL = 0.0; double Fb = 0.0; double Ff = 0.0; /*przesuniecie, sila hamowania i tarcia*/
|
||||||
|
|||||||
@@ -3751,14 +3751,23 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
|
|||||||
Sign(nrot * M_PI * WheelDiameter - V) *
|
Sign(nrot * M_PI * WheelDiameter - V) *
|
||||||
Adhesive(RunningTrack.friction) * TotalMassxg,
|
Adhesive(RunningTrack.friction) * TotalMassxg,
|
||||||
dt, nrot);
|
dt, nrot);
|
||||||
Fwheels = Sign(nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction);
|
Fwheels = Sign(temp_nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction);
|
||||||
if (Fwheels*Sign(V)>0)
|
if (Fwheels*Sign(V)>0)
|
||||||
{
|
{
|
||||||
FTrain = Fwheels - Fb;
|
FTrain = Fwheels + Fb*Sign(V);
|
||||||
|
}
|
||||||
|
else if (FTrain*Sign(V)>0)
|
||||||
|
{
|
||||||
|
Fb = FTrain*Sign(V) - Fwheels*Sign(V);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Fb = FTrain - Fwheels;
|
Fb = -Fwheels*Sign(V);
|
||||||
|
FTrain = 0;
|
||||||
|
}
|
||||||
|
if (nrot < 0.1)
|
||||||
|
{
|
||||||
|
WheelFlat = sqrt(sqr(WheelFlat) + abs(Fwheels) / NAxles*Vel*0.000002);
|
||||||
}
|
}
|
||||||
if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0)
|
if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0)
|
||||||
{
|
{
|
||||||
@@ -4648,7 +4657,7 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
{
|
{
|
||||||
PosRatio = -Sign(V) * DirAbsolute * eimv[eimv_Fr] /
|
PosRatio = -Sign(V) * DirAbsolute * eimv[eimv_Fr] /
|
||||||
(eimc[eimc_p_Fh] *
|
(eimc[eimc_p_Fh] *
|
||||||
Max0R(dtrans / MaxBrakePress[0], AnPos) /*dizel_fill*/);
|
Max0R(Max0R(dtrans,0.01) / MaxBrakePress[0], AnPos) /*dizel_fill*/);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PosRatio = 0;
|
PosRatio = 0;
|
||||||
@@ -4699,11 +4708,11 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
if( ( SlippingWheels ) ) {
|
if( ( SlippingWheels ) ) {
|
||||||
PosRatio = 0;
|
PosRatio = 0;
|
||||||
tmp = 9;
|
tmp = 9;
|
||||||
Sandbox( true, range::local );
|
Sandbox( true, range::unit );
|
||||||
} // przeciwposlizg
|
} // przeciwposlizg
|
||||||
else {
|
else {
|
||||||
// switch sandbox off
|
// switch sandbox off
|
||||||
Sandbox( false, range::local );
|
Sandbox( false, range::unit );
|
||||||
}
|
}
|
||||||
|
|
||||||
dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.1), -0.1) * 2 *
|
dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.1), -0.1) * 2 *
|
||||||
@@ -4740,6 +4749,13 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
-Sign(V) * (DirAbsolute)*std::min(
|
-Sign(V) * (DirAbsolute)*std::min(
|
||||||
eimc[eimc_p_Ph] * 3.6 / (Vel != 0.0 ? Vel : 0.001),
|
eimc[eimc_p_Ph] * 3.6 / (Vel != 0.0 ? Vel : 0.001),
|
||||||
std::min(-eimc[eimc_p_Fh] * dizel_fill, eimv[eimv_FMAXMAX]));
|
std::min(-eimc[eimc_p_Fh] * dizel_fill, eimv[eimv_FMAXMAX]));
|
||||||
|
double pr = dizel_fill;
|
||||||
|
if (EIMCLogForce)
|
||||||
|
pr = -log(1 - 4 * pr) / log(5);
|
||||||
|
eimv[eimv_Fr] =
|
||||||
|
-Sign(V) * (DirAbsolute)*std::min(
|
||||||
|
eimc[eimc_p_Ph] * 3.6 / (Vel != 0.0 ? Vel : 0.001),
|
||||||
|
std::min(-eimc[eimc_p_Fh] * pr, eimv[eimv_FMAXMAX]));
|
||||||
//*Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0]))
|
//*Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0]))
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -4751,9 +4767,13 @@ double TMoverParameters::TractionForce(double dt)
|
|||||||
eimv[eimv_Fmax] = eimv[eimv_Fful] * dizel_fill;
|
eimv[eimv_Fmax] = eimv[eimv_Fful] * dizel_fill;
|
||||||
// else
|
// else
|
||||||
// eimv[eimv_Fmax]:=Min0R(eimc[eimc_p_F0]*dizel_fill,eimv[eimv_Fful]);
|
// eimv[eimv_Fmax]:=Min0R(eimc[eimc_p_F0]*dizel_fill,eimv[eimv_Fful]);
|
||||||
|
double pr = dizel_fill;
|
||||||
|
if (EIMCLogForce)
|
||||||
|
pr = log(1 + 4 * pr) / log(5);
|
||||||
|
eimv[eimv_Fr] = eimv[eimv_Fful] * pr;
|
||||||
}
|
}
|
||||||
|
|
||||||
eimv[eimv_ks] = eimv[eimv_Fmax] / eimv[eimv_FMAXMAX];
|
eimv[eimv_ks] = eimv[eimv_Fr] / eimv[eimv_FMAXMAX];
|
||||||
eimv[eimv_df] = eimv[eimv_ks] * eimc[eimc_s_dfmax];
|
eimv[eimv_df] = eimv[eimv_ks] * eimc[eimc_s_dfmax];
|
||||||
eimv[eimv_fp] = DirAbsolute * enrot * eimc[eimc_s_p] +
|
eimv[eimv_fp] = DirAbsolute * enrot * eimc[eimc_s_p] +
|
||||||
eimv[eimv_df]; // do przemyslenia dzialanie pp z tmpV
|
eimv[eimv_df]; // do przemyslenia dzialanie pp z tmpV
|
||||||
@@ -4924,7 +4944,7 @@ double TMoverParameters::v2n(void)
|
|||||||
n = V / (M_PI * WheelDiameter); // predkosc obrotowa wynikajaca z liniowej [obr/s]
|
n = V / (M_PI * WheelDiameter); // predkosc obrotowa wynikajaca z liniowej [obr/s]
|
||||||
deltan = n - nrot; //"pochodna" prędkości obrotowej
|
deltan = n - nrot; //"pochodna" prędkości obrotowej
|
||||||
if (SlippingWheels)
|
if (SlippingWheels)
|
||||||
if (std::abs(deltan) < 0.01)
|
if (std::abs(deltan) < 0.001)
|
||||||
SlippingWheels = false; // wygaszenie poslizgu
|
SlippingWheels = false; // wygaszenie poslizgu
|
||||||
if (SlippingWheels) // nie ma zwiazku z predkoscia liniowa V
|
if (SlippingWheels) // nie ma zwiazku z predkoscia liniowa V
|
||||||
{ // McZapkie-221103: uszkodzenia kol podczas poslizgu
|
{ // McZapkie-221103: uszkodzenia kol podczas poslizgu
|
||||||
@@ -6923,7 +6943,7 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( true == extract_value( AirLeakRate, "AirLeakRate", line, "" ) ) {
|
if( true == extract_value( AirLeakRate, "AirLeakRate", line, "" ) ) {
|
||||||
// the parameter is provided in form of a multiplier, where 1.0 means the default rate of 0.001
|
// the parameter is provided in form of a multiplier, where 1.0 means the default rate of 0.01
|
||||||
AirLeakRate *= 0.01;
|
AirLeakRate *= 0.01;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7149,6 +7169,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
|||||||
|
|
||||||
if( asb == "Manual" ) { ASBType = 1; }
|
if( asb == "Manual" ) { ASBType = 1; }
|
||||||
else if( asb == "Automatic" ) { ASBType = 2; }
|
else if( asb == "Automatic" ) { ASBType = 2; }
|
||||||
|
else if (asb == "Yes") { ASBType = 128; }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@@ -7397,6 +7418,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
|
|||||||
extract_value( eimc[ eimc_p_Imax ], "Imax", Input, "" );
|
extract_value( eimc[ eimc_p_Imax ], "Imax", Input, "" );
|
||||||
extract_value( eimc[ eimc_p_abed ], "abed", Input, "" );
|
extract_value( eimc[ eimc_p_abed ], "abed", Input, "" );
|
||||||
extract_value( eimc[ eimc_p_eped ], "edep", Input, "" );
|
extract_value( eimc[ eimc_p_eped ], "edep", Input, "" );
|
||||||
|
EIMCLogForce = ( extract_value( "eimclf", Input ) == "Yes" );
|
||||||
|
|
||||||
Flat = ( extract_value( "Flat", Input ) == "1" );
|
Flat = ( extract_value( "Flat", Input ) == "1" );
|
||||||
|
|
||||||
@@ -7826,10 +7848,13 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
|
|||||||
BrakeCtrlPos = static_cast<int>( Handle->GetPos( bh_NP ) );
|
BrakeCtrlPos = static_cast<int>( Handle->GetPos( bh_NP ) );
|
||||||
else
|
else
|
||||||
BrakeCtrlPos = static_cast<int>( Handle->GetPos( bh_RP ) );
|
BrakeCtrlPos = static_cast<int>( Handle->GetPos( bh_RP ) );
|
||||||
|
/*
|
||||||
|
// NOTE: disabled and left up to the driver, if there's any
|
||||||
MainSwitch( false );
|
MainSwitch( false );
|
||||||
PantFront( true );
|
PantFront( true );
|
||||||
PantRear( true );
|
PantRear( true );
|
||||||
MainSwitch( true );
|
MainSwitch( true );
|
||||||
|
*/
|
||||||
ActiveDir = 0; // Dir; //nastawnik kierunkowy - musi być ustawiane osobno!
|
ActiveDir = 0; // Dir; //nastawnik kierunkowy - musi być ustawiane osobno!
|
||||||
DirAbsolute = ActiveDir * CabNo; // kierunek jazdy względem sprzęgów
|
DirAbsolute = ActiveDir * CabNo; // kierunek jazdy względem sprzęgów
|
||||||
LimPipePress = CntrlPipePress;
|
LimPipePress = CntrlPipePress;
|
||||||
|
|||||||
@@ -435,8 +435,6 @@ void TNESt3::ForceEmptiness()
|
|||||||
Miedzypoj->CreatePress(0);
|
Miedzypoj->CreatePress(0);
|
||||||
CntrlRes->CreatePress(0);
|
CntrlRes->CreatePress(0);
|
||||||
|
|
||||||
BrakeStatus = 0;
|
|
||||||
|
|
||||||
ValveRes->Act();
|
ValveRes->Act();
|
||||||
BrakeRes->Act();
|
BrakeRes->Act();
|
||||||
Miedzypoj->Act();
|
Miedzypoj->Act();
|
||||||
|
|||||||
@@ -413,6 +413,7 @@ void TBrake::ForceEmptiness()
|
|||||||
{
|
{
|
||||||
ValveRes->CreatePress(0);
|
ValveRes->CreatePress(0);
|
||||||
BrakeRes->CreatePress(0);
|
BrakeRes->CreatePress(0);
|
||||||
|
|
||||||
ValveRes->Act();
|
ValveRes->Act();
|
||||||
BrakeRes->Act();
|
BrakeRes->Act();
|
||||||
}
|
}
|
||||||
@@ -757,6 +758,17 @@ double TESt::GetCRP()
|
|||||||
return CntrlRes->P();
|
return CntrlRes->P();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TESt::ForceEmptiness() {
|
||||||
|
|
||||||
|
ValveRes->CreatePress( 0 );
|
||||||
|
BrakeRes->CreatePress( 0 );
|
||||||
|
CntrlRes->CreatePress( 0 );
|
||||||
|
|
||||||
|
ValveRes->Act();
|
||||||
|
BrakeRes->Act();
|
||||||
|
CntrlRes->Act();
|
||||||
|
}
|
||||||
|
|
||||||
//---EP2---
|
//---EP2---
|
||||||
|
|
||||||
void TEStEP2::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )
|
void TEStEP2::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )
|
||||||
@@ -1462,9 +1474,15 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel )
|
|||||||
|
|
||||||
// powtarzacz — podwojny zawor zwrotny
|
// powtarzacz — podwojny zawor zwrotny
|
||||||
temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP);
|
temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP);
|
||||||
|
double speed = 1;
|
||||||
|
if ((ASBP < 0.1) && ((BrakeStatus & b_asb) == b_asb))
|
||||||
|
{
|
||||||
|
temp = 0;
|
||||||
|
speed = 3;
|
||||||
|
}
|
||||||
|
|
||||||
if ((BrakeCyl->P() > temp))
|
if ((BrakeCyl->P() > temp))
|
||||||
dv = -PFVd(BrakeCyl->P(), 0, 0.02 * SizeBC, temp) * dt;
|
dv = -PFVd(BrakeCyl->P(), 0, 0.02 * SizeBC * speed, temp) * dt;
|
||||||
else if ((BrakeCyl->P() < temp))
|
else if ((BrakeCyl->P() < temp))
|
||||||
dv = PFVa(BVP, BrakeCyl->P(), 0.02 * SizeBC, temp) * dt;
|
dv = PFVa(BVP, BrakeCyl->P(), 0.02 * SizeBC, temp) * dt;
|
||||||
else
|
else
|
||||||
@@ -1721,6 +1739,17 @@ double TCV1::GetCRP()
|
|||||||
return CntrlRes->P();
|
return CntrlRes->P();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TCV1::ForceEmptiness() {
|
||||||
|
|
||||||
|
ValveRes->CreatePress( 0 );
|
||||||
|
BrakeRes->CreatePress( 0 );
|
||||||
|
CntrlRes->CreatePress( 0 );
|
||||||
|
|
||||||
|
ValveRes->Act();
|
||||||
|
BrakeRes->Act();
|
||||||
|
CntrlRes->Act();
|
||||||
|
}
|
||||||
|
|
||||||
//---CV1-L-TR---
|
//---CV1-L-TR---
|
||||||
|
|
||||||
void TCV1L_TR::SetLBP( double const P )
|
void TCV1L_TR::SetLBP( double const P )
|
||||||
@@ -1995,7 +2024,8 @@ double TKE::GetPF( double const PP, double const dt, double const Vel )
|
|||||||
// luzowanie CH
|
// luzowanie CH
|
||||||
// temp:=Max0R(BCP,LBP);
|
// temp:=Max0R(BCP,LBP);
|
||||||
IMP = Max0R(IMP / temp, Max0R(LBP, ASBP * int((BrakeStatus & b_asb) == b_asb)));
|
IMP = Max0R(IMP / temp, Max0R(LBP, ASBP * int((BrakeStatus & b_asb) == b_asb)));
|
||||||
|
if ((ASBP < 0.1) && ((BrakeStatus & b_asb) == b_asb))
|
||||||
|
IMP = 0;
|
||||||
// luzowanie CH
|
// luzowanie CH
|
||||||
if ((BCP > IMP + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.25))
|
if ((BCP > IMP + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.25))
|
||||||
dv = PFVd(BCP, 0, 0.05, IMP) * dt;
|
dv = PFVd(BCP, 0, 0.05, IMP) * dt;
|
||||||
@@ -2090,6 +2120,21 @@ void TKE::SetLBP( double const P )
|
|||||||
LBP = P;
|
LBP = P;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TKE::ForceEmptiness() {
|
||||||
|
|
||||||
|
ValveRes->CreatePress( 0 );
|
||||||
|
BrakeRes->CreatePress( 0 );
|
||||||
|
CntrlRes->CreatePress( 0 );
|
||||||
|
ImplsRes->CreatePress( 0 );
|
||||||
|
Brak2Res->CreatePress( 0 );
|
||||||
|
|
||||||
|
ValveRes->Act();
|
||||||
|
BrakeRes->Act();
|
||||||
|
CntrlRes->Act();
|
||||||
|
ImplsRes->Act();
|
||||||
|
Brak2Res->Act();
|
||||||
|
}
|
||||||
|
|
||||||
//---KRANY---
|
//---KRANY---
|
||||||
|
|
||||||
double TDriverHandle::GetPF(double const i_bcp, double PP, double HP, double dt, double ep)
|
double TDriverHandle::GetPF(double const i_bcp, double PP, double HP, double dt, double ep)
|
||||||
|
|||||||
@@ -260,6 +260,7 @@ class TESt : public TBrake {
|
|||||||
void CheckReleaser(double dt); //odluzniacz
|
void CheckReleaser(double dt); //odluzniacz
|
||||||
double CVs(double BP); //napelniacz sterujacego
|
double CVs(double BP); //napelniacz sterujacego
|
||||||
double BVs(double BCP); //napelniacz pomocniczego
|
double BVs(double BCP); //napelniacz pomocniczego
|
||||||
|
void ForceEmptiness() /*override*/; // wymuszenie bycia pustym
|
||||||
|
|
||||||
inline TESt(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
|
inline TESt(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
|
||||||
TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)
|
TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)
|
||||||
@@ -410,6 +411,7 @@ public:
|
|||||||
void CheckState( double const BCP, double &dV1 );
|
void CheckState( double const BCP, double &dV1 );
|
||||||
double CVs( double const BP );
|
double CVs( double const BP );
|
||||||
double BVs( double const BCP );
|
double BVs( double const BCP );
|
||||||
|
void ForceEmptiness() /*override*/; // wymuszenie bycia pustym
|
||||||
|
|
||||||
inline TCV1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
|
inline TCV1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
|
||||||
TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)
|
TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)
|
||||||
@@ -482,6 +484,7 @@ class TKE : public TBrake { //Knorr Einheitsbauart — jeden do wszystkiego
|
|||||||
void PLC( double const mass ); //wspolczynnik cisnienia przystawki wazacej
|
void PLC( double const mass ); //wspolczynnik cisnienia przystawki wazacej
|
||||||
void SetLP( double const TM, double const LM, double const TBP ); //parametry przystawki wazacej
|
void SetLP( double const TM, double const LM, double const TBP ); //parametry przystawki wazacej
|
||||||
void SetLBP( double const P ); //cisnienie z hamulca pomocniczego
|
void SetLBP( double const P ); //cisnienie z hamulca pomocniczego
|
||||||
|
void ForceEmptiness() /*override*/; // wymuszenie bycia pustym
|
||||||
|
|
||||||
inline TKE(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
|
inline TKE(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
|
||||||
TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)
|
TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)
|
||||||
|
|||||||
63
MemCell.cpp
63
MemCell.cpp
@@ -16,26 +16,23 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "MemCell.h"
|
#include "MemCell.h"
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "simulation.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "usefull.h"
|
|
||||||
#include "Driver.h"
|
|
||||||
#include "Event.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// legacy constructor
|
||||||
TMemCell::TMemCell(vector3 *p)
|
TMemCell::TMemCell(vector3 *p)
|
||||||
{
|
{
|
||||||
fValue1 = fValue2 = 0;
|
fValue1 = fValue2 = 0;
|
||||||
vPosition =
|
location(
|
||||||
p ? *p : vector3(0, 0, 0); // ustawienie współrzędnych, bo do TGroundNode nie ma dostępu
|
p ? *p : vector3() ); // ustawienie współrzędnych, bo do TGroundNode nie ma dostępu
|
||||||
bCommand = false; // komenda wysłana
|
bCommand = false; // komenda wysłana
|
||||||
OnSent = NULL;
|
OnSent = NULL;
|
||||||
}
|
}
|
||||||
void TMemCell::Init()
|
|
||||||
{
|
TMemCell::TMemCell( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||||
}
|
|
||||||
void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask )
|
void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask )
|
||||||
{
|
{
|
||||||
if (CheckMask & update_memadd)
|
if (CheckMask & update_memadd)
|
||||||
@@ -103,10 +100,12 @@ TCommandType TMemCell::CommandCheck()
|
|||||||
bool TMemCell::Load(cParser *parser)
|
bool TMemCell::Load(cParser *parser)
|
||||||
{
|
{
|
||||||
std::string token;
|
std::string token;
|
||||||
parser->getTokens(1, false); // case sensitive
|
parser->getTokens( 6, false );
|
||||||
*parser >> szText;
|
|
||||||
parser->getTokens( 2, false );
|
|
||||||
*parser
|
*parser
|
||||||
|
>> m_area.center.x
|
||||||
|
>> m_area.center.y
|
||||||
|
>> m_area.center.z
|
||||||
|
>> szText
|
||||||
>> fValue1
|
>> fValue1
|
||||||
>> fValue2;
|
>> fValue2;
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
@@ -121,7 +120,7 @@ bool TMemCell::Load(cParser *parser)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMemCell::PutCommand(TController *Mech, vector3 *Loc)
|
void TMemCell::PutCommand( TController *Mech, glm::dvec3 const *Loc )
|
||||||
{ // wysłanie zawartości komórki do AI
|
{ // wysłanie zawartości komórki do AI
|
||||||
if (Mech)
|
if (Mech)
|
||||||
Mech->PutCommand(szText, fValue1, fValue2, Loc);
|
Mech->PutCommand(szText, fValue1, fValue2, Loc);
|
||||||
@@ -150,11 +149,6 @@ bool TMemCell::Compare( std::string const &szTestText, double const fTestValue1,
|
|||||||
&& ( !TestFlag( CheckMask, conditional_memval2 ) || ( fValue2 == fTestValue2 ) ) );
|
&& ( !TestFlag( CheckMask, conditional_memval2 ) || ( fValue2 == fTestValue2 ) ) );
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TMemCell::Render()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TMemCell::IsVelocity()
|
bool TMemCell::IsVelocity()
|
||||||
{ // sprawdzenie, czy event odczytu tej komórki ma być do skanowania, czy do kolejkowania
|
{ // sprawdzenie, czy event odczytu tej komórki ma być do skanowania, czy do kolejkowania
|
||||||
if (eCommand == cm_SetVelocity)
|
if (eCommand == cm_SetVelocity)
|
||||||
@@ -169,11 +163,38 @@ void TMemCell::StopCommandSent()
|
|||||||
if (!bCommand)
|
if (!bCommand)
|
||||||
return;
|
return;
|
||||||
bCommand = false;
|
bCommand = false;
|
||||||
if (OnSent) // jeśli jest event
|
if( OnSent ) {
|
||||||
Global::AddToQuery(OnSent, NULL);
|
// jeśli jest event
|
||||||
|
simulation::Events.AddToQuery( OnSent, nullptr );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void TMemCell::AssignEvents(TEvent *e)
|
void TMemCell::AssignEvents(TEvent *e)
|
||||||
{ // powiązanie eventu
|
{ // powiązanie eventu
|
||||||
OnSent = e;
|
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" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, sends content of all cells to the log
|
||||||
|
void
|
||||||
|
memory_table::log_all() {
|
||||||
|
|
||||||
|
for( auto *cell : m_items ) {
|
||||||
|
|
||||||
|
WriteLog( "Memcell \"" + cell->name() + "\": ["
|
||||||
|
+ cell->Text() + "] ["
|
||||||
|
+ to_string( cell->Value1(), 2 ) + "] ["
|
||||||
|
+ to_string( cell->Value2(), 2 ) + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
91
MemCell.h
91
MemCell.h
@@ -10,52 +10,69 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
|
#include "scenenode.h"
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
|
#include "Names.h"
|
||||||
|
|
||||||
|
class TMemCell : public editor::basic_node {
|
||||||
|
|
||||||
class TMemCell
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
Math3D::vector3 vPosition;
|
|
||||||
std::string szText;
|
|
||||||
double fValue1;
|
|
||||||
double fValue2;
|
|
||||||
TCommandType eCommand;
|
|
||||||
bool bCommand; // czy zawiera komendę dla zatrzymanego AI
|
|
||||||
TEvent *OnSent; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład
|
|
||||||
public:
|
public:
|
||||||
std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
|
std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
|
||||||
|
|
||||||
|
TMemCell( scene::node_data const &Nodedata );
|
||||||
|
// legacy constructor
|
||||||
TMemCell( Math3D::vector3 *p );
|
TMemCell( Math3D::vector3 *p );
|
||||||
void Init();
|
|
||||||
void UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask );
|
void
|
||||||
bool Load(cParser *parser);
|
UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask );
|
||||||
void PutCommand( TController *Mech, Math3D::vector3 *Loc );
|
bool
|
||||||
bool Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask );
|
Load(cParser *parser);
|
||||||
bool Render();
|
void
|
||||||
inline std::string const &Text() { return szText; }
|
PutCommand( TController *Mech, glm::dvec3 const *Loc );
|
||||||
inline double Value1()
|
bool
|
||||||
{
|
Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask );
|
||||||
return fValue1;
|
std::string const &
|
||||||
};
|
Text() const {
|
||||||
inline double Value2()
|
return szText; }
|
||||||
{
|
double
|
||||||
return fValue2;
|
Value1() const {
|
||||||
};
|
return fValue1; };
|
||||||
inline Math3D::vector3 Position()
|
double
|
||||||
{
|
Value2() const {
|
||||||
return vPosition;
|
return fValue2; };
|
||||||
};
|
TCommandType
|
||||||
inline TCommandType Command()
|
Command() const {
|
||||||
{
|
return eCommand; };
|
||||||
return eCommand;
|
bool
|
||||||
};
|
StopCommand() const {
|
||||||
inline bool StopCommand()
|
return bCommand; };
|
||||||
{
|
|
||||||
return bCommand;
|
|
||||||
};
|
|
||||||
void StopCommandSent();
|
void StopCommandSent();
|
||||||
TCommandType CommandCheck();
|
TCommandType CommandCheck();
|
||||||
bool IsVelocity();
|
bool IsVelocity();
|
||||||
void AssignEvents(TEvent *e);
|
void AssignEvents(TEvent *e);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// content
|
||||||
|
std::string szText;
|
||||||
|
double fValue1 { 0.0 };
|
||||||
|
double fValue2 { 0.0 };
|
||||||
|
// other
|
||||||
|
TCommandType eCommand { cm_Unknown };
|
||||||
|
bool bCommand { false }; // czy zawiera komendę dla zatrzymanego AI
|
||||||
|
TEvent *OnSent { nullptr }; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class memory_table : public basic_table<TMemCell> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// legacy method, initializes traction after deserialization from scenario file
|
||||||
|
void
|
||||||
|
InitCells();
|
||||||
|
// legacy method, sends content of all cells to the log
|
||||||
|
void
|
||||||
|
log_all();
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
113
Model3d.cpp
113
Model3d.cpp
@@ -988,11 +988,11 @@ TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &
|
|||||||
|
|
||||||
// data offset is used to determine data offset of each submodel into single shared geometry bank
|
// data offset is used to determine data offset of each submodel into single shared geometry bank
|
||||||
// (the offsets are part of legacy system which we now need to work around for backward compatibility)
|
// (the offsets are part of legacy system which we now need to work around for backward compatibility)
|
||||||
|
|
||||||
if( Child )
|
if( Child )
|
||||||
Child->create_geometry( Dataoffset, Bank );
|
Child->create_geometry( Dataoffset, Bank );
|
||||||
|
|
||||||
if( false == Vertices.empty() ) {
|
if( false == Vertices.empty() ) {
|
||||||
|
|
||||||
tVboPtr = static_cast<int>( Dataoffset );
|
tVboPtr = static_cast<int>( Dataoffset );
|
||||||
Dataoffset += Vertices.size();
|
Dataoffset += Vertices.size();
|
||||||
// conveniently all relevant custom node types use GL_POINTS, or we'd have to determine the type on individual basis
|
// conveniently all relevant custom node types use GL_POINTS, or we'd have to determine the type on individual basis
|
||||||
@@ -1003,69 +1003,35 @@ TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &
|
|||||||
m_geometry = GfxRenderer.Insert( Vertices, Bank, type );
|
m_geometry = GfxRenderer.Insert( Vertices, Bank, type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( m_geometry != 0 ) {
|
||||||
|
// calculate bounding radius while we're at it
|
||||||
|
// NOTE: doesn't take into account transformation hierarchy TODO: implement it
|
||||||
|
float squaredradius { 0.f };
|
||||||
|
// if this happens to be root node it may already have non-squared radius of the largest child
|
||||||
|
// since we're comparing squared radii, we need to square it back for correct results
|
||||||
|
m_boundingradius *= m_boundingradius;
|
||||||
|
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
|
||||||
|
squaredradius = static_cast<float>( glm::length2( vertex.position ) );
|
||||||
|
if( squaredradius > m_boundingradius ) {
|
||||||
|
m_boundingradius = squaredradius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( m_boundingradius > 0.f ) { m_boundingradius = std::sqrt( m_boundingradius ); }
|
||||||
|
// adjust overall radius if needed
|
||||||
|
// NOTE: the method to access root submodel is... less than ideal
|
||||||
|
auto *root { this };
|
||||||
|
while( root->Parent != nullptr ) {
|
||||||
|
root = root->Parent;
|
||||||
|
}
|
||||||
|
root->m_boundingradius = std::max(
|
||||||
|
root->m_boundingradius,
|
||||||
|
m_boundingradius );
|
||||||
|
}
|
||||||
|
|
||||||
if( Next )
|
if( Next )
|
||||||
Next->create_geometry( Dataoffset, Bank );
|
Next->create_geometry( Dataoffset, Bank );
|
||||||
}
|
}
|
||||||
|
|
||||||
// places contained geometry in provided ground node
|
|
||||||
void
|
|
||||||
TSubModel::convert( TGroundNode &Groundnode ) const {
|
|
||||||
|
|
||||||
Groundnode.asName = pName;
|
|
||||||
Groundnode.Ambient = f4Ambient;
|
|
||||||
Groundnode.Diffuse = f4Diffuse;
|
|
||||||
Groundnode.Specular = f4Specular;
|
|
||||||
Groundnode.m_material = m_material;
|
|
||||||
Groundnode.iFlags = (
|
|
||||||
( true == GfxRenderer.Material( m_material ).has_alpha ) ?
|
|
||||||
0x20 :
|
|
||||||
0x10 );
|
|
||||||
|
|
||||||
if( m_geometry == null_handle ) { return; }
|
|
||||||
|
|
||||||
std::size_t vertexcount { 0 };
|
|
||||||
std::vector<TGroundVertex> importedvertices;
|
|
||||||
TGroundVertex vertex, vertex1, vertex2;
|
|
||||||
for( auto const &sourcevertex : GfxRenderer.Vertices( m_geometry ) ) {
|
|
||||||
vertex.position = sourcevertex.position;
|
|
||||||
vertex.normal = sourcevertex.normal;
|
|
||||||
vertex.texture = sourcevertex.texture;
|
|
||||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
|
||||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
|
||||||
else if( vertexcount >= 2 ) {
|
|
||||||
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
|
||||||
importedvertices.emplace_back( vertex1 );
|
|
||||||
importedvertices.emplace_back( vertex2 );
|
|
||||||
importedvertices.emplace_back( vertex );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++vertexcount;
|
|
||||||
if( vertexcount > 2 ) { vertexcount = 0; } // start new triangle if needed
|
|
||||||
}
|
|
||||||
if( Groundnode.Piece == nullptr ) {
|
|
||||||
Groundnode.Piece = new piece_node();
|
|
||||||
}
|
|
||||||
Groundnode.iNumVerts = importedvertices.size();
|
|
||||||
if( Groundnode.iNumVerts > 0 ) {
|
|
||||||
|
|
||||||
Groundnode.Piece->vertices.swap( importedvertices );
|
|
||||||
|
|
||||||
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
|
||||||
Groundnode.pCenter += vertex.position;
|
|
||||||
}
|
|
||||||
Groundnode.pCenter /= Groundnode.iNumVerts;
|
|
||||||
|
|
||||||
double r { 0.0 };
|
|
||||||
double tf;
|
|
||||||
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
|
||||||
tf = glm::length2( vertex.position - glm::dvec3{ Groundnode.pCenter } );
|
|
||||||
if( tf > r )
|
|
||||||
r = tf;
|
|
||||||
}
|
|
||||||
Groundnode.fSquareRadius += r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSubModel::ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular )
|
void TSubModel::ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular )
|
||||||
{ // ustawienie kolorów dla modelu terenu
|
{ // ustawienie kolorów dla modelu terenu
|
||||||
f4Ambient = glm::vec4( Ambient, 1.0f );
|
f4Ambient = glm::vec4( Ambient, 1.0f );
|
||||||
@@ -1151,7 +1117,8 @@ TModel3d::~TModel3d() {
|
|||||||
|
|
||||||
if (iFlags & 0x0200) {
|
if (iFlags & 0x0200) {
|
||||||
// wczytany z pliku tekstowego, submodele sprzątają same
|
// wczytany z pliku tekstowego, submodele sprzątają same
|
||||||
Root = nullptr;
|
SafeDelete( Root );
|
||||||
|
// Root = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// wczytano z pliku binarnego (jest właścicielem tablic)
|
// wczytano z pliku binarnego (jest właścicielem tablic)
|
||||||
@@ -1639,7 +1606,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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;
|
m_material = null_handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1750,18 +1717,11 @@ void TModel3d::Init()
|
|||||||
return; // operacje zostały już wykonane
|
return; // operacje zostały już wykonane
|
||||||
if (Root)
|
if (Root)
|
||||||
{
|
{
|
||||||
if (iFlags & 0x0200) // jeśli wczytano z pliku tekstowego
|
if (iFlags & 0x0200) {
|
||||||
{ // jest jakiś dziwny błąd, że obkręcany ma być tylko ostatni submodel
|
// jeśli wczytano z pliku tekstowego jest jakiś dziwny błąd,
|
||||||
// głównego łańcucha
|
// że obkręcany ma być tylko ostatni submodel głównego łańcucha
|
||||||
// TSubModel *p=Root;
|
// argumet określa, czy wykonać pierwotny obrót
|
||||||
// do
|
Root->InitialRotate(true);
|
||||||
//{p->InitialRotate(true); //ostatniemu należy się konwersja układu
|
|
||||||
// współrzędnych
|
|
||||||
// p=p->NextGet();
|
|
||||||
//}
|
|
||||||
// while (p->NextGet())
|
|
||||||
// Root->InitialRotate(false); //a poprzednim tylko optymalizacja
|
|
||||||
Root->InitialRotate(true); // argumet określa, czy wykonać pierwotny obrót
|
|
||||||
}
|
}
|
||||||
iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu
|
iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu
|
||||||
if (iNumVerts) {
|
if (iNumVerts) {
|
||||||
@@ -1779,11 +1739,6 @@ void TModel3d::Init()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void TModel3d::BreakHierarhy()
|
|
||||||
{
|
|
||||||
Error("Not implemented yet :(");
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// 2012-02 funkcje do tworzenia terenu z E3D
|
// 2012-02 funkcje do tworzenia terenu z E3D
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|||||||
21
Model3d.h
21
Model3d.h
@@ -50,14 +50,18 @@ enum TAnimType // rodzaj animacji
|
|||||||
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
|
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace scene {
|
||||||
|
class shape_node;
|
||||||
|
}
|
||||||
|
|
||||||
class TModel3d;
|
class TModel3d;
|
||||||
class TGroundNode;
|
|
||||||
|
|
||||||
class TSubModel
|
class TSubModel
|
||||||
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
|
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
||||||
friend class TDynamicObject; // temporary etc
|
friend class TDynamicObject; // temporary etc
|
||||||
|
friend class scene::shape_node; // temporary etc
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum normalization {
|
enum normalization {
|
||||||
@@ -130,10 +134,8 @@ private:
|
|||||||
|
|
||||||
public: // chwilowo
|
public: // chwilowo
|
||||||
float3 v_TransVector { 0.0f, 0.0f, 0.0f };
|
float3 v_TransVector { 0.0f, 0.0f, 0.0f };
|
||||||
/*
|
|
||||||
basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
|
|
||||||
*/
|
|
||||||
vertex_array Vertices;
|
vertex_array Vertices;
|
||||||
|
float m_boundingradius { 0 };
|
||||||
size_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację
|
size_t iAnimOwner{ 0 }; // roboczy numer egzemplarza, który ustawił animację
|
||||||
TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane
|
TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane
|
||||||
public:
|
public:
|
||||||
@@ -163,9 +165,6 @@ public:
|
|||||||
TSubModel * NextGet() { return Next; };
|
TSubModel * NextGet() { return Next; };
|
||||||
TSubModel * ChildGet() { return Child; };
|
TSubModel * ChildGet() { return Child; };
|
||||||
int TriangleAdd(TModel3d *m, material_handle tex, int tri);
|
int TriangleAdd(TModel3d *m, material_handle tex, int tri);
|
||||||
/*
|
|
||||||
basic_vertex * TrianglePtr(int tex, int pos, glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
|
|
||||||
*/
|
|
||||||
void SetRotate(float3 vNewRotateAxis, float fNewAngle);
|
void SetRotate(float3 vNewRotateAxis, float fNewAngle);
|
||||||
void SetRotateXYZ(vector3 vNewAngles);
|
void SetRotateXYZ(vector3 vNewAngles);
|
||||||
void SetRotateXYZ(float3 vNewAngles);
|
void SetRotateXYZ(float3 vNewAngles);
|
||||||
@@ -215,8 +214,6 @@ public:
|
|||||||
std::vector<float4x4>&);
|
std::vector<float4x4>&);
|
||||||
void serialize_geometry( std::ostream &Output ) const;
|
void serialize_geometry( std::ostream &Output ) const;
|
||||||
// places contained geometry in provided ground node
|
// places contained geometry in provided ground node
|
||||||
void convert( TGroundNode &Groundnode ) const;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TModel3d : public CMesh
|
class TModel3d : public CMesh
|
||||||
@@ -236,6 +233,11 @@ private:
|
|||||||
std::string asBinary; // nazwa pod którą zapisać model binarny
|
std::string asBinary; // nazwa pod którą zapisać model binarny
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
public:
|
public:
|
||||||
|
float bounding_radius() const {
|
||||||
|
return (
|
||||||
|
Root ?
|
||||||
|
Root->m_boundingradius :
|
||||||
|
0.f ); }
|
||||||
inline TSubModel * GetSMRoot() { return (Root); };
|
inline TSubModel * GetSMRoot() { return (Root); };
|
||||||
TModel3d();
|
TModel3d();
|
||||||
~TModel3d();
|
~TModel3d();
|
||||||
@@ -246,7 +248,6 @@ public:
|
|||||||
void LoadFromBinFile(std::string const &FileName, bool dynamic);
|
void LoadFromBinFile(std::string const &FileName, bool dynamic);
|
||||||
bool LoadFromFile(std::string const &FileName, bool dynamic);
|
bool LoadFromFile(std::string const &FileName, bool dynamic);
|
||||||
void SaveToBinFile(std::string const &FileName);
|
void SaveToBinFile(std::string const &FileName);
|
||||||
void BreakHierarhy();
|
|
||||||
int Flags() const { return iFlags; };
|
int Flags() const { return iFlags; };
|
||||||
void Init();
|
void Init();
|
||||||
std::string NameGet() { return m_filename; };
|
std::string NameGet() { return m_filename; };
|
||||||
|
|||||||
81
Names.h
81
Names.h
@@ -13,55 +13,52 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
template <typename Type_>
|
template <typename Type_>
|
||||||
class TNames {
|
class basic_table {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// types:
|
// destructor
|
||||||
|
~basic_table() {
|
||||||
// constructors:
|
for( auto *item : m_items ) {
|
||||||
TNames() = default;
|
delete item; } }
|
||||||
|
// methods
|
||||||
// destructor:
|
// adds provided item to the collection. returns: true if there's no duplicate with the same name, false otherwise
|
||||||
|
|
||||||
// methods:
|
|
||||||
// dodanie obiektu z wskaźnikiem. updates data field if the object already exists. returns true for insertion, false for update
|
|
||||||
bool
|
bool
|
||||||
Add( int const Type, std::string const &Name, Type_ Data ) {
|
insert( Type_ *Item ) {
|
||||||
|
m_items.emplace_back( Item );
|
||||||
auto lookup = find_map( Type ).emplace( Name, Data );
|
auto const itemname = Item->name();
|
||||||
if( lookup.second == false ) {
|
if( ( true == itemname.empty() ) || ( itemname == "none" ) ) {
|
||||||
// record already exists, update it
|
|
||||||
lookup.first->second = Data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// new record inserted, bail out
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
auto const itemhandle { m_items.size() - 1 };
|
||||||
|
// add item name to the map
|
||||||
|
auto mapping = m_itemmap.emplace( itemname, itemhandle );
|
||||||
|
if( true == mapping.second ) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// returns pointer associated with provided label, or nullptr if there's no match
|
// cell with this name already exists; update mapping to point to the new one, for backward compatibility
|
||||||
Type_
|
mapping.first->second = itemhandle;
|
||||||
Find( int const Type, std::string const &Name ) {
|
return false; }
|
||||||
|
// locates item with specified name. returns pointer to the item, or nullptr
|
||||||
|
Type_ *
|
||||||
|
find( std::string const &Name ) {
|
||||||
|
auto lookup = m_itemmap.find( Name );
|
||||||
|
return (
|
||||||
|
lookup != m_itemmap.end() ?
|
||||||
|
m_items[ lookup->second ] :
|
||||||
|
nullptr ); }
|
||||||
|
|
||||||
auto const &map = find_map( Type );
|
protected:
|
||||||
auto const lookup = map.find( Name );
|
// types
|
||||||
if( lookup != map.end() ) { return lookup->second; }
|
using type_sequence = std::deque<Type_ *>;
|
||||||
else { return nullptr; }
|
using type_map = std::unordered_map<std::string, std::size_t>;
|
||||||
}
|
// members
|
||||||
|
type_sequence m_items;
|
||||||
|
type_map m_itemmap;
|
||||||
|
|
||||||
private:
|
public:
|
||||||
// types:
|
// data access
|
||||||
typedef std::unordered_map<std::string, Type_> type_map;
|
type_sequence &
|
||||||
typedef std::unordered_map<int, type_map> typemap_map;
|
sequence() {
|
||||||
|
return m_items; }
|
||||||
|
|
||||||
// methods:
|
|
||||||
// returns database stored with specified type key; creates new database if needed.
|
|
||||||
type_map &
|
|
||||||
find_map( int const Type ) {
|
|
||||||
|
|
||||||
return m_maps.emplace( Type, type_map() ).first->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// members:
|
|
||||||
typemap_map m_maps; // list of object maps of types specified so far
|
|
||||||
};
|
};
|
||||||
|
|||||||
153
Segment.cpp
153
Segment.cpp
@@ -59,8 +59,8 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
CPointIn = NewCPointIn;
|
CPointIn = NewCPointIn;
|
||||||
Point2 = NewPoint2;
|
Point2 = NewPoint2;
|
||||||
// poprawienie przechyłki
|
// poprawienie przechyłki
|
||||||
fRoll1 = DegToRad(fNewRoll1); // Ra: przeliczone jest bardziej przydatne do obliczeń
|
fRoll1 = glm::radians(fNewRoll1); // Ra: przeliczone jest bardziej przydatne do obliczeń
|
||||||
fRoll2 = DegToRad(fNewRoll2);
|
fRoll2 = glm::radians(fNewRoll2);
|
||||||
if (Global::bRollFix)
|
if (Global::bRollFix)
|
||||||
{ // Ra: poprawianie przechyłki
|
{ // Ra: poprawianie przechyłki
|
||||||
// Przechyłka powinna być na środku wewnętrznej szyny, a standardowo jest w osi
|
// Przechyłka powinna być na środku wewnętrznej szyny, a standardowo jest w osi
|
||||||
@@ -78,7 +78,7 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
CPointOut.y += w1; // prosty ma wektory jednostkowe
|
CPointOut.y += w1; // prosty ma wektory jednostkowe
|
||||||
pOwner->MovedUp1(w1); // zwrócić trzeba informację o podwyższeniu podsypki
|
pOwner->MovedUp1(w1); // zwrócić trzeba informację o podwyższeniu podsypki
|
||||||
}
|
}
|
||||||
if (fRoll2 != 0.0)
|
if (fRoll2 != 0.f)
|
||||||
{
|
{
|
||||||
double w2 = std::abs(std::sin(fRoll2) * 0.75); // 0.5*w2+0.0325; //0.75m dla 1.435
|
double w2 = std::abs(std::sin(fRoll2) * 0.75); // 0.5*w2+0.0325; //0.75m dla 1.435
|
||||||
Point2.y += w2; // modyfikacja musi być przed policzeniem dalszych parametrów
|
Point2.y += w2; // modyfikacja musi być przed policzeniem dalszych parametrów
|
||||||
@@ -87,9 +87,9 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
// zwrócić trzeba informację o podwyższeniu podsypki
|
// zwrócić trzeba informację o podwyższeniu podsypki
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// kąt w planie, żeby nie liczyć wielokrotnie
|
||||||
// Ra: ten kąt jeszcze do przemyślenia jest
|
// Ra: ten kąt jeszcze do przemyślenia jest
|
||||||
fDirection = -atan2(Point2.x - Point1.x,
|
fDirection = -std::atan2(Point2.x - Point1.x, Point2.z - Point1.z);
|
||||||
Point2.z - Point1.z); // kąt w planie, żeby nie liczyć wielokrotnie
|
|
||||||
bCurve = bIsCurve;
|
bCurve = bIsCurve;
|
||||||
if (bCurve)
|
if (bCurve)
|
||||||
{ // przeliczenie współczynników wielomianu, będzie mniej mnożeń i można policzyć pochodne
|
{ // przeliczenie współczynników wielomianu, będzie mniej mnożeń i można policzyć pochodne
|
||||||
@@ -101,10 +101,9 @@ bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, M
|
|||||||
else
|
else
|
||||||
fLength = (Point1 - Point2).Length();
|
fLength = (Point1 - Point2).Length();
|
||||||
fStep = fNewStep;
|
fStep = fNewStep;
|
||||||
if (fLength <= 0)
|
if (fLength <= 0) {
|
||||||
{
|
|
||||||
ErrorLog( "Bad geometry: zero length spline \"" + pOwner->NameGet() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
ErrorLog( "Bad track: zero length spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||||
// MessageBox(0,"Length<=0","TSegment::Init",MB_OK);
|
|
||||||
fLength = 0.01; // crude workaround TODO: fix this properly
|
fLength = 0.01; // crude workaround TODO: fix this properly
|
||||||
/*
|
/*
|
||||||
return false; // zerowe nie mogą być
|
return false; // zerowe nie mogą być
|
||||||
@@ -206,7 +205,7 @@ double TSegment::GetTFromS(double const s) const
|
|||||||
// Newton's method failed. If this happens, increase iterations or
|
// Newton's method failed. If this happens, increase iterations or
|
||||||
// tolerance or integration accuracy.
|
// tolerance or integration accuracy.
|
||||||
// return -1; //Ra: tu nigdy nie dojdzie
|
// 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 track: shape estimation failed for spline \"" + pOwner->name() + "\" (location: " + to_string( glm::dvec3{ Point1 } ) + ")" );
|
||||||
// MessageBox(0,"Too many iterations","GetTFromS",MB_OK);
|
// MessageBox(0,"Too many iterations","GetTFromS",MB_OK);
|
||||||
return fTime;
|
return fTime;
|
||||||
};
|
};
|
||||||
@@ -324,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
|
||||||
{ // 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
|
if (bCurve) {
|
||||||
double t = GetTFromS(fDistance); // aproksymacja dystansu na krzywej Beziera na parametr (t)
|
// można by wprowadzić uproszczony wzór dla okręgów płaskich
|
||||||
p = RaInterpolate(t);
|
auto const t = GetTFromS(fDistance); // aproksymacja dystansu na krzywej Beziera na parametr (t)
|
||||||
a.x = (1.0 - t) * fRoll1 + (t)*fRoll2; // przechyłka w danym miejscu (zmienia się liniowo)
|
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
|
// 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)
|
auto const tangent = t * ( t * 3.0 * vA + vB + vB ) + vC;
|
||||||
a.z = -atan2(t * (t * 3.0 * vA.x + vB.x + vB.x) + vC.x,
|
// pochylenie krzywej (w pionie)
|
||||||
t * (t * 3.0 * vA.z + vB.z + vB.z) + vC.z); // kierunek krzywej w planie
|
a.y = std::atan( tangent.y );
|
||||||
|
// kierunek krzywej w planie
|
||||||
|
a.z = -std::atan2( tangent.x, tangent.z );
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{ // wyliczenie dla odcinka prostego jest prostsze
|
// wyliczenie dla odcinka prostego jest prostsze
|
||||||
double t = fDistance / fLength; // zerowych torów nie ma
|
auto const t = fDistance / fLength; // zerowych torów nie ma
|
||||||
p = ((1.0 - t) * Point1 + (t)*Point2);
|
p = FastGetPoint( t );
|
||||||
a.x = (1.0 - t) * fRoll1 + (t)*fRoll2; // przechyłka w danym miejscu (zmienia się liniowo)
|
// przechyłka w danym miejscu (zmienia się liniowo)
|
||||||
|
a.x = interpolate<double>( fRoll1, fRoll2, t );
|
||||||
a.y = fStoop; // pochylenie toru prostego
|
a.y = fStoop; // pochylenie toru prostego
|
||||||
a.z = fDirection; // kierunek toru w planie
|
a.z = fDirection; // kierunek toru w planie
|
||||||
}
|
}
|
||||||
@@ -355,7 +359,7 @@ Math3D::vector3 TSegment::FastGetPoint(double const t) const
|
|||||||
interpolate( Point1, Point2, t ) );
|
interpolate( Point1, Point2, t ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, Math3D::vector3 **p, bool bRender)
|
bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, const basic_vertex *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, float fOffsetX, glm::vec3 **p, bool bRender)
|
||||||
{ // generowanie trójkątów dla odcinka trajektorii ruchu
|
{ // generowanie trójkątów dla odcinka trajektorii ruchu
|
||||||
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
|
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
|
||||||
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
|
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
|
||||||
@@ -365,13 +369,14 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
|
|||||||
if( !fTsBuffer )
|
if( !fTsBuffer )
|
||||||
return false; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
return false; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
||||||
|
|
||||||
Math3D::vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
|
glm::vec3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
|
||||||
double s, step, fOffset, tv1, tv2, t, fEnd;
|
float s, step, fOffset, tv1, tv2, t, fEnd;
|
||||||
bool const trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
|
bool const trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
|
||||||
iNumShapePoints = std::abs( iNumShapePoints );
|
iNumShapePoints = std::abs( iNumShapePoints );
|
||||||
fTextureLength *= Texturescale;
|
float const texturelength = fTextureLength * Texturescale;
|
||||||
|
float const texturescale = Texturescale;
|
||||||
|
|
||||||
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
|
float m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
|
||||||
step = fStep;
|
step = fStep;
|
||||||
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
|
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
|
||||||
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
|
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
|
||||||
@@ -379,9 +384,14 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
|
|||||||
t = fTsBuffer[ i ]; // tabela wattości t dla segmentów
|
t = fTsBuffer[ i ]; // tabela wattości t dla segmentów
|
||||||
// BUG: length of spline can be 0, we should skip geometry generation for such cases
|
// BUG: length of spline can be 0, we should skip geometry generation for such cases
|
||||||
fOffset = 0.1 / fLength; // pierwsze 10cm
|
fOffset = 0.1 / fLength; // pierwsze 10cm
|
||||||
pos1 = FastGetPoint( t ); // wektor początku segmentu
|
pos1 = glm::dvec3{ FastGetPoint( t ) - Origin }; // wektor początku segmentu
|
||||||
dir = FastGetDirection( t, fOffset ); // wektor kierunku
|
dir = glm::dvec3{ FastGetDirection( t, fOffset ) }; // wektor kierunku
|
||||||
parallel1 = Normalize( Math3D::vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
|
parallel1 = glm::vec3{ -dir.z, 0.f, dir.x }; // wektor poprzeczny
|
||||||
|
if( glm::length2( parallel1 ) == 0.f ) {
|
||||||
|
// temporary workaround for malformed situations with control points placed above endpoints
|
||||||
|
parallel1 = glm::vec3{ glm::dvec3{ FastGetPoint_1() - FastGetPoint_0() } };
|
||||||
|
}
|
||||||
|
parallel1 = glm::normalize( parallel1 );
|
||||||
if( iEnd == 0 )
|
if( iEnd == 0 )
|
||||||
iEnd = iSegCount;
|
iEnd = iSegCount;
|
||||||
fEnd = fLength * double( iEnd ) / double( iSegCount );
|
fEnd = fLength * double( iEnd ) / double( iSegCount );
|
||||||
@@ -406,26 +416,31 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
|
|||||||
while( tv1 < 0.0 ) {
|
while( tv1 < 0.0 ) {
|
||||||
tv1 += 1.0;
|
tv1 += 1.0;
|
||||||
}
|
}
|
||||||
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
|
tv2 = tv1 - step / texturelength; // mapowanie na końcu segmentu
|
||||||
|
|
||||||
t = fTsBuffer[ i ]; // szybsze od GetTFromS(s);
|
t = fTsBuffer[ i ]; // szybsze od GetTFromS(s);
|
||||||
pos2 = FastGetPoint( t );
|
pos2 = glm::dvec3{ FastGetPoint( t ) - Origin };
|
||||||
dir = FastGetDirection( t, fOffset ); // nowy wektor kierunku
|
dir = glm::dvec3{ FastGetDirection( t, fOffset ) }; // nowy wektor kierunku
|
||||||
parallel2 = Normalize( Math3D::vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
|
parallel2 = glm::vec3{ -dir.z, 0.f, dir.x }; // wektor poprzeczny
|
||||||
|
if( glm::length2( parallel2 ) == 0.f ) {
|
||||||
|
// temporary workaround for malformed situations with control points placed above endpoints
|
||||||
|
parallel2 = glm::vec3{ glm::dvec3{ FastGetPoint_1() - FastGetPoint_0() } };
|
||||||
|
}
|
||||||
|
parallel2 = glm::normalize( parallel2 );
|
||||||
|
|
||||||
if( trapez ) {
|
if( trapez ) {
|
||||||
for( int j = 0; j < iNumShapePoints; ++j ) {
|
for( int j = 0; j < iNumShapePoints; ++j ) {
|
||||||
pt = parallel1 * ( jmm1 * ( ShapePoints[ j ].x - fOffsetX ) + m1 * ShapePoints[ j + iNumShapePoints ].x ) + pos1;
|
pt = parallel1 * ( jmm1 * ( ShapePoints[ j ].position.x - fOffsetX ) + m1 * ShapePoints[ j + iNumShapePoints ].position.x ) + pos1;
|
||||||
pt.y += jmm1 * ShapePoints[ j ].y + m1 * ShapePoints[ j + iNumShapePoints ].y;
|
pt.y += jmm1 * ShapePoints[ j ].position.y + m1 * ShapePoints[ j + iNumShapePoints ].position.y;
|
||||||
pt -= Origin;
|
// pt -= Origin;
|
||||||
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel1;
|
norm = ( jmm1 * ShapePoints[ j ].normal.x + m1 * ShapePoints[ j + iNumShapePoints ].normal.x ) * parallel1;
|
||||||
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
|
norm.y += jmm1 * ShapePoints[ j ].normal.y + m1 * ShapePoints[ j + iNumShapePoints ].normal.y;
|
||||||
if( bRender ) {
|
if( bRender ) {
|
||||||
// skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
// skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
||||||
Output.emplace_back(
|
Output.emplace_back(
|
||||||
glm::vec3 { pt.x, pt.y, pt.z },
|
pt,
|
||||||
glm::vec3 { norm.x, norm.y, norm.z },
|
glm::normalize( norm ),
|
||||||
glm::vec2 { ( jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z ) / Texturescale, tv1 } );
|
glm::vec2 { ( jmm1 * ShapePoints[ j ].texture.x + m1 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv1 } );
|
||||||
}
|
}
|
||||||
if( p ) // jeśli jest wskaźnik do tablicy
|
if( p ) // jeśli jest wskaźnik do tablicy
|
||||||
if( *p )
|
if( *p )
|
||||||
@@ -435,17 +450,17 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
|
|||||||
( *p )++;
|
( *p )++;
|
||||||
} // zapamiętanie brzegu jezdni
|
} // zapamiętanie brzegu jezdni
|
||||||
// dla trapezu drugi koniec ma inne współrzędne
|
// dla trapezu drugi koniec ma inne współrzędne
|
||||||
pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].x - fOffsetX ) + m2 * ShapePoints[ j + iNumShapePoints ].x ) + pos2;
|
pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].position.x - fOffsetX ) + m2 * ShapePoints[ j + iNumShapePoints ].position.x ) + pos2;
|
||||||
pt.y += jmm2 * ShapePoints[ j ].y + m2 * ShapePoints[ j + iNumShapePoints ].y;
|
pt.y += jmm2 * ShapePoints[ j ].position.y + m2 * ShapePoints[ j + iNumShapePoints ].position.y;
|
||||||
pt -= Origin;
|
// pt -= Origin;
|
||||||
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel2;
|
norm = ( jmm1 * ShapePoints[ j ].normal.x + m1 * ShapePoints[ j + iNumShapePoints ].normal.x ) * parallel2;
|
||||||
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
|
norm.y += jmm1 * ShapePoints[ j ].normal.y + m1 * ShapePoints[ j + iNumShapePoints ].normal.y;
|
||||||
if( bRender ) {
|
if( bRender ) {
|
||||||
// skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
// skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
||||||
Output.emplace_back(
|
Output.emplace_back(
|
||||||
glm::vec3 { pt.x, pt.y, pt.z },
|
pt,
|
||||||
glm::vec3 { norm.x, norm.y, norm.z },
|
glm::normalize( norm ),
|
||||||
glm::vec2 { ( jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z ) / Texturescale, tv2 } );
|
glm::vec2 { ( jmm2 * ShapePoints[ j ].texture.x + m2 * ShapePoints[ j + iNumShapePoints ].texture.x ) / texturescale, tv2 } );
|
||||||
}
|
}
|
||||||
if( p ) // jeśli jest wskaźnik do tablicy
|
if( p ) // jeśli jest wskaźnik do tablicy
|
||||||
if( *p )
|
if( *p )
|
||||||
@@ -460,27 +475,27 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
|
|||||||
if( bRender ) {
|
if( bRender ) {
|
||||||
for( int j = 0; j < iNumShapePoints; ++j ) {
|
for( int j = 0; j < iNumShapePoints; ++j ) {
|
||||||
//łuk z jednym profilem
|
//łuk z jednym profilem
|
||||||
pt = parallel1 * ( ShapePoints[ j ].x - fOffsetX ) + pos1;
|
pt = parallel1 * ( ShapePoints[ j ].position.x - fOffsetX ) + pos1;
|
||||||
pt.y += ShapePoints[ j ].y;
|
pt.y += ShapePoints[ j ].position.y;
|
||||||
pt -= Origin;
|
// pt -= Origin;
|
||||||
norm = ShapePoints[ j ].n.x * parallel1;
|
norm = ShapePoints[ j ].normal.x * parallel1;
|
||||||
norm.y += ShapePoints[ j ].n.y;
|
norm.y += ShapePoints[ j ].normal.y;
|
||||||
|
|
||||||
Output.emplace_back(
|
Output.emplace_back(
|
||||||
glm::vec3 { pt.x, pt.y, pt.z },
|
pt,
|
||||||
glm::vec3 { norm.x, norm.y, norm.z },
|
glm::normalize( norm ),
|
||||||
glm::vec2 { ShapePoints[ j ].z / Texturescale, tv1 } );
|
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv1 } );
|
||||||
|
|
||||||
pt = parallel2 * ShapePoints[ j ].x + pos2;
|
pt = parallel2 * ShapePoints[ j ].position.x + pos2;
|
||||||
pt.y += ShapePoints[ j ].y;
|
pt.y += ShapePoints[ j ].position.y;
|
||||||
pt -= Origin;
|
// pt -= Origin;
|
||||||
norm = ShapePoints[ j ].n.x * parallel2;
|
norm = ShapePoints[ j ].normal.x * parallel2;
|
||||||
norm.y += ShapePoints[ j ].n.y;
|
norm.y += ShapePoints[ j ].normal.y;
|
||||||
|
|
||||||
Output.emplace_back(
|
Output.emplace_back(
|
||||||
glm::vec3 { pt.x, pt.y, pt.z },
|
pt,
|
||||||
glm::vec3 { norm.x, norm.y, norm.z },
|
glm::normalize( norm ),
|
||||||
glm::vec2 { ShapePoints[ j ].z / Texturescale, tv2 } );
|
glm::vec2 { ShapePoints[ j ].texture.x / texturescale, tv2 } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
50
Segment.h
50
Segment.h
@@ -14,44 +14,13 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
#include "usefull.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=d; n.y=e; n.z=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
|
class TSegment
|
||||||
{ // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
|
{ // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
|
||||||
private:
|
private:
|
||||||
Math3D::vector3 Point1, CPointOut, CPointIn, Point2;
|
Math3D::vector3 Point1, CPointOut, CPointIn, Point2;
|
||||||
double fRoll1 = 0.0,
|
float
|
||||||
fRoll2 = 0.0; // przechyłka na końcach
|
fRoll1{ 0.f },
|
||||||
|
fRoll2{ 0.f }; // przechyłka na końcach
|
||||||
double fLength = 0.0; // długość policzona
|
double fLength = 0.0; // długość policzona
|
||||||
double *fTsBuffer = nullptr; // wartości parametru krzywej dla równych odcinków
|
double *fTsBuffer = nullptr; // wartości parametru krzywej dla równych odcinków
|
||||||
double fStep = 0.0;
|
double fStep = 0.0;
|
||||||
@@ -60,7 +29,6 @@ class TSegment
|
|||||||
double fStoop = 0.0; // Ra: kąt wzniesienia; dla łuku od Point1
|
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
|
Math3D::vector3 vA, vB, vC; // współczynniki wielomianów trzeciego stopnia vD==Point1
|
||||||
TTrack *pOwner = nullptr; // wskaźnik na właściciela
|
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
|
Math3D::vector3
|
||||||
GetFirstDerivative(double const fTime) const;
|
GetFirstDerivative(double const fTime) const;
|
||||||
@@ -118,18 +86,18 @@ public:
|
|||||||
FastGetPoint_1() const {
|
FastGetPoint_1() const {
|
||||||
return Point2; };
|
return Point2; };
|
||||||
inline
|
inline
|
||||||
double
|
float
|
||||||
GetRoll(double const Distance) const {
|
GetRoll(double const Distance) const {
|
||||||
return interpolate( fRoll1, fRoll2, Distance / fLength ); }
|
return interpolate( fRoll1, fRoll2, static_cast<float>(Distance / fLength) ); }
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
GetRolls(double &r1, double &r2) const {
|
GetRolls(float &r1, float &r2) const {
|
||||||
// pobranie przechyłek (do generowania trójkątów)
|
// pobranie przechyłek (do generowania trójkątów)
|
||||||
r1 = fRoll1;
|
r1 = fRoll1;
|
||||||
r2 = fRoll2; }
|
r2 = fRoll2; }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, Math3D::vector3 **p = nullptr, bool bRender = true);
|
RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, basic_vertex const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, float fOffsetX = 0.f, glm::vec3 **p = nullptr, bool bRender = true);
|
||||||
void
|
void
|
||||||
Render();
|
Render();
|
||||||
inline
|
inline
|
||||||
@@ -140,10 +108,6 @@ public:
|
|||||||
int
|
int
|
||||||
RaSegCount() const {
|
RaSegCount() const {
|
||||||
return fTsBuffer ? iSegCount : 1; };
|
return fTsBuffer ? iSegCount : 1; };
|
||||||
inline
|
|
||||||
void
|
|
||||||
AngleSet(int const i, double const a) {
|
|
||||||
fAngle[i] = a; };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -765,8 +765,11 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
|
|||||||
Filename.erase( traitpos );
|
Filename.erase( traitpos );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Filename.rfind( '.' ) != std::string::npos )
|
if( ( Filename.rfind( '.' ) != std::string::npos )
|
||||||
Filename.erase( Filename.rfind( '.' ) ); // trim extension if there's one
|
&& ( Filename.rfind( '.' ) != Filename.rfind( ".." ) + 1 ) ) {
|
||||||
|
// trim extension if there's one, but don't mistake folder traverse for extension
|
||||||
|
Filename.erase( Filename.rfind( '.' ) );
|
||||||
|
}
|
||||||
|
|
||||||
std::replace(Filename.begin(), Filename.end(), '\\', '/'); // fix slashes
|
std::replace(Filename.begin(), Filename.end(), '\\', '/'); // fix slashes
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
namespace Timer
|
namespace Timer {
|
||||||
{
|
|
||||||
|
subsystem_stopwatches subsystem;
|
||||||
|
|
||||||
double DeltaTime, DeltaRenderTime;
|
double DeltaTime, DeltaRenderTime;
|
||||||
double fFPS{ 0.0f };
|
double fFPS{ 0.0f };
|
||||||
|
|||||||
36
Timer.h
36
Timer.h
@@ -9,8 +9,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Timer
|
namespace Timer {
|
||||||
{
|
|
||||||
|
|
||||||
double GetTime();
|
double GetTime();
|
||||||
|
|
||||||
@@ -28,6 +27,39 @@ double GetFPS();
|
|||||||
void ResetTimers();
|
void ResetTimers();
|
||||||
|
|
||||||
void UpdateTimers(bool pause);
|
void UpdateTimers(bool pause);
|
||||||
|
|
||||||
|
class stopwatch {
|
||||||
|
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
start() {
|
||||||
|
m_start = std::chrono::steady_clock::now(); }
|
||||||
|
void
|
||||||
|
stop() {
|
||||||
|
m_accumulator = 0.95f * m_accumulator + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - m_start ) ).count() / 1000.f; }
|
||||||
|
float
|
||||||
|
average() const {
|
||||||
|
return m_accumulator / 20.f;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> m_start { std::chrono::steady_clock::now() };
|
||||||
|
float m_accumulator { 1000.f / 30.f * 20.f }; // 20 last samples, initial 'neutral' rate of 30 fps
|
||||||
|
};
|
||||||
|
|
||||||
|
struct subsystem_stopwatches {
|
||||||
|
stopwatch gfx_total;
|
||||||
|
stopwatch gfx_color;
|
||||||
|
stopwatch gfx_shadows;
|
||||||
|
stopwatch gfx_reflections;
|
||||||
|
stopwatch gfx_swap;
|
||||||
|
stopwatch sim_total;
|
||||||
|
stopwatch sim_dynamics;
|
||||||
|
stopwatch sim_events;
|
||||||
|
stopwatch sim_ai;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern subsystem_stopwatches subsystem;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
126
Track.h
126
Track.h
@@ -10,23 +10,29 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "GL/glew.h"
|
#include <vector>
|
||||||
#include "ResourceManager.h"
|
#include <deque>
|
||||||
|
|
||||||
#include "Segment.h"
|
#include "Segment.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
#include "scenenode.h"
|
||||||
|
#include "Names.h"
|
||||||
|
|
||||||
typedef enum
|
namespace scene {
|
||||||
{
|
class basic_cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TTrackType {
|
||||||
tt_Unknown,
|
tt_Unknown,
|
||||||
tt_Normal,
|
tt_Normal,
|
||||||
tt_Switch,
|
tt_Switch,
|
||||||
tt_Table,
|
tt_Table,
|
||||||
tt_Cross,
|
tt_Cross,
|
||||||
tt_Tributary
|
tt_Tributary
|
||||||
} TTrackType;
|
};
|
||||||
// McZapkie-100502
|
// McZapkie-100502
|
||||||
typedef enum
|
|
||||||
{
|
enum TEnvironmentType {
|
||||||
e_unknown = -1,
|
e_unknown = -1,
|
||||||
e_flat = 0,
|
e_flat = 0,
|
||||||
e_mountains,
|
e_mountains,
|
||||||
@@ -34,7 +40,7 @@ typedef enum
|
|||||||
e_tunnel,
|
e_tunnel,
|
||||||
e_bridge,
|
e_bridge,
|
||||||
e_bank
|
e_bank
|
||||||
} TEnvironmentType;
|
};
|
||||||
// Ra: opracować alternatywny system cieni/świateł z definiowaniem koloru oświetlenia w halach
|
// Ra: opracować alternatywny system cieni/świateł z definiowaniem koloru oświetlenia w halach
|
||||||
|
|
||||||
class TEvent;
|
class TEvent;
|
||||||
@@ -49,49 +55,43 @@ class TSwitchExtension
|
|||||||
TSwitchExtension(TTrack *owner, int const what);
|
TSwitchExtension(TTrack *owner, int const what);
|
||||||
~TSwitchExtension();
|
~TSwitchExtension();
|
||||||
std::shared_ptr<TSegment> Segments[6]; // dwa tory od punktu 1, pozosta³e dwa od 2? Ra 140101: 6 po³¹czeñ dla skrzy¿owañ
|
std::shared_ptr<TSegment> Segments[6]; // dwa tory od punktu 1, pozosta³e dwa od 2? Ra 140101: 6 po³¹czeñ dla skrzy¿owañ
|
||||||
// TTrack *trNear[4]; //tory do³¹czone do punktów 1, 2, 3 i 4
|
|
||||||
// dotychczasowe [2]+[2] wskaŸniki zamieniæ na nowe [4]
|
|
||||||
TTrack *pNexts[2]; // tory do³¹czone do punktów 2 i 4
|
TTrack *pNexts[2]; // tory do³¹czone do punktów 2 i 4
|
||||||
TTrack *pPrevs[2]; // tory do³¹czone do punktów 1 i 3
|
TTrack *pPrevs[2]; // tory do³¹czone do punktów 1 i 3
|
||||||
int iNextDirection[2]; // to te¿ z [2]+[2] przerobiæ na [4]
|
int iNextDirection[2]; // to te¿ z [2]+[2] przerobiæ na [4]
|
||||||
int iPrevDirection[2];
|
int iPrevDirection[2];
|
||||||
int CurrentIndex = 0; // dla zwrotnicy
|
int CurrentIndex = 0; // dla zwrotnicy
|
||||||
double fOffset = 0.0,
|
float
|
||||||
fDesiredOffset = 0.0; // aktualne i docelowe położenie napędu iglic
|
fOffset{ 0.f },
|
||||||
double fOffsetSpeed = 0.1; // prędkość liniowa ruchu iglic
|
fDesiredOffset{ 0.f }; // aktualne i docelowe położenie napędu iglic
|
||||||
double fOffsetDelay = 0.05; // opóźnienie ruchu drugiej iglicy względem pierwszej // dodatkowy ruch drugiej iglicy po zablokowaniu pierwszej na opornicy
|
float fOffsetSpeed = 0.1f; // prędkość liniowa ruchu iglic
|
||||||
|
float fOffsetDelay = 0.05f; // opóźnienie ruchu drugiej iglicy względem pierwszej // dodatkowy ruch drugiej iglicy po zablokowaniu pierwszej na opornicy
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{ // zmienne potrzebne tylko dla zwrotnicy
|
{ // zmienne potrzebne tylko dla zwrotnicy
|
||||||
double fOffset1,
|
float fOffset1,
|
||||||
fOffset2; // przesunięcia iglic - 0=na wprost
|
fOffset2; // przesunięcia iglic - 0=na wprost
|
||||||
bool RightSwitch; // czy zwrotnica w prawo
|
bool RightSwitch; // czy zwrotnica w prawo
|
||||||
};
|
};
|
||||||
struct
|
struct
|
||||||
{ // zmienne potrzebne tylko dla obrotnicy/przesuwnicy
|
{ // zmienne potrzebne tylko dla obrotnicy/przesuwnicy
|
||||||
TGroundNode *pMyNode; // dla obrotnicy do wtórnego podłączania torów
|
|
||||||
// TAnimContainer *pAnim; //animator modelu dla obrotnicy
|
// TAnimContainer *pAnim; //animator modelu dla obrotnicy
|
||||||
TAnimModel *pModel; // na razie model
|
TAnimModel *pModel; // na razie model
|
||||||
};
|
};
|
||||||
struct
|
struct
|
||||||
{ // zmienne dla skrzyżowania
|
{ // zmienne dla skrzyżowania
|
||||||
int iRoads; // ile dróg się spotyka?
|
int iRoads; // ile dróg się spotyka?
|
||||||
Math3D::vector3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze
|
glm::vec3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze
|
||||||
// int iPoints; // liczba faktycznie użytych wierzchołków nawierzchni
|
|
||||||
bool bPoints; // czy utworzone?
|
bool bPoints; // czy utworzone?
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
bool bMovement = false; // czy w trakcie animacji
|
bool bMovement = false; // czy w trakcie animacji
|
||||||
int iLeftVBO = 0,
|
scene::basic_cell *pOwner = nullptr; // TODO: convert this to observer pattern
|
||||||
iRightVBO = 0; // indeksy iglic w VBO
|
|
||||||
TSubRect *pOwner = nullptr; // sektor, któremu trzeba zgłosić animację
|
|
||||||
TTrack *pNextAnim = nullptr; // następny tor do animowania
|
TTrack *pNextAnim = nullptr; // następny tor do animowania
|
||||||
TEvent *evPlus = nullptr,
|
TEvent *evPlus = nullptr,
|
||||||
*evMinus = nullptr; // zdarzenia sygnalizacji rozprucia
|
*evMinus = nullptr; // zdarzenia sygnalizacji rozprucia
|
||||||
float fVelocity = -1.0; // maksymalne ograniczenie prędkości (ustawianej eventem)
|
float fVelocity = -1.0; // maksymalne ograniczenie prędkości (ustawianej eventem)
|
||||||
Math3D::vector3 vTrans; // docelowa translacja przesuwnicy
|
Math3D::vector3 vTrans; // docelowa translacja przesuwnicy
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TIsolated
|
class TIsolated
|
||||||
@@ -106,7 +106,7 @@ class TIsolated
|
|||||||
TMemCell *pMemCell = nullptr; // automatyczna komórka pamięci, która współpracuje z odcinkiem izolowanym
|
TMemCell *pMemCell = nullptr; // automatyczna komórka pamięci, która współpracuje z odcinkiem izolowanym
|
||||||
TIsolated();
|
TIsolated();
|
||||||
TIsolated(const std::string &n, TIsolated *i);
|
TIsolated(const std::string &n, TIsolated *i);
|
||||||
~TIsolated();
|
static void DeleteAll();
|
||||||
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
|
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
|
||||||
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
|
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
|
||||||
bool Busy() {
|
bool Busy() {
|
||||||
@@ -118,12 +118,11 @@ class TIsolated
|
|||||||
};
|
};
|
||||||
|
|
||||||
// trajektoria ruchu - opakowanie
|
// trajektoria ruchu - opakowanie
|
||||||
class TTrack /*: public Resource*/ {
|
class TTrack : public editor::basic_node {
|
||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
private:
|
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
|
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<TSwitchExtension> SwitchExtension; // dodatkowe dane do toru, który jest zwrotnicą
|
||||||
std::shared_ptr<TSegment> Segment;
|
std::shared_ptr<TSegment> Segment;
|
||||||
@@ -132,7 +131,7 @@ private:
|
|||||||
|
|
||||||
// McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
|
// McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
|
||||||
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
|
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
|
||||||
double fRadiusTable[ 2 ]; // dwa promienie, drugi dla zwrotnicy
|
double fRadiusTable[ 2 ] = { 0.0, 0.0 }; // dwa promienie, drugi dla zwrotnicy
|
||||||
float fTexLength = 4.0f; // długość powtarzania tekstury w metrach
|
float fTexLength = 4.0f; // długość powtarzania tekstury w metrach
|
||||||
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
|
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
|
||||||
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
|
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
|
||||||
@@ -140,6 +139,7 @@ private:
|
|||||||
float fTexWidth = 0.9f; // szerokość boku
|
float fTexWidth = 0.9f; // szerokość boku
|
||||||
float fTexSlope = 0.9f;
|
float fTexSlope = 0.9f;
|
||||||
|
|
||||||
|
glm::dvec3 m_origin;
|
||||||
material_handle m_material1 = 0; // tekstura szyn albo nawierzchni
|
material_handle m_material1 = 0; // tekstura szyn albo nawierzchni
|
||||||
material_handle m_material2 = 0; // tekstura automatycznej podsypki albo pobocza
|
material_handle m_material2 = 0; // tekstura automatycznej podsypki albo pobocza
|
||||||
typedef std::vector<geometry_handle> geometryhandle_sequence;
|
typedef std::vector<geometry_handle> geometryhandle_sequence;
|
||||||
@@ -173,7 +173,6 @@ public:
|
|||||||
int iQualityFlag = 20;
|
int iQualityFlag = 20;
|
||||||
int iDamageFlag = 0;
|
int iDamageFlag = 0;
|
||||||
TEnvironmentType eEnvironment = e_flat; // dźwięk i oświetlenie
|
TEnvironmentType eEnvironment = e_flat; // dźwięk i oświetlenie
|
||||||
bool bVisible = true; // czy rysowany
|
|
||||||
int iAction = 0; // czy modyfikowany eventami (specjalna obsługa przy skanowaniu)
|
int iAction = 0; // czy modyfikowany eventami (specjalna obsługa przy skanowaniu)
|
||||||
float fOverhead = -1.0; // można normalnie pobierać prąd (0 dla jazdy bezprądowej po danym odcinku, >0-z opuszczonym i ograniczeniem prędkości)
|
float fOverhead = -1.0; // można normalnie pobierać prąd (0 dla jazdy bezprądowej po danym odcinku, >0-z opuszczonym i ograniczeniem prędkości)
|
||||||
private:
|
private:
|
||||||
@@ -183,12 +182,15 @@ public:
|
|||||||
double fTrackLength = 100.0; // długość z wpisu, nigdzie nie używana
|
double fTrackLength = 100.0; // długość z wpisu, nigdzie nie używana
|
||||||
double fRadius = 0.0; // promień, dla zwrotnicy kopiowany z tabeli
|
double fRadius = 0.0; // promień, dla zwrotnicy kopiowany z tabeli
|
||||||
bool ScannedFlag = false; // McZapkie: do zaznaczania kolorem torów skanowanych przez AI
|
bool ScannedFlag = false; // McZapkie: do zaznaczania kolorem torów skanowanych przez AI
|
||||||
TTraction *hvOverhead = nullptr; // drut zasilający do szybkiego znalezienia (nie używany)
|
TGroundNode *nFouling[ 2 ] = { nullptr, nullptr }; // współrzędne ukresu albo oporu kozła
|
||||||
TGroundNode *nFouling[ 2 ]; // współrzędne ukresu albo oporu kozła
|
|
||||||
|
TTrack( scene::node_data const &Nodedata );
|
||||||
|
// legacy constructor
|
||||||
|
TTrack( std::string Name );
|
||||||
|
virtual ~TTrack();
|
||||||
|
|
||||||
TTrack(TGroundNode *g);
|
|
||||||
~TTrack();
|
|
||||||
void Init();
|
void Init();
|
||||||
|
static bool sort_by_material( TTrack const *Left, TTrack const *Right );
|
||||||
static TTrack * Create400m(int what, double dx);
|
static TTrack * Create400m(int what, double dx);
|
||||||
TTrack * NullCreate(int dir);
|
TTrack * NullCreate(int dir);
|
||||||
inline bool IsEmpty() {
|
inline bool IsEmpty() {
|
||||||
@@ -207,7 +209,7 @@ public:
|
|||||||
return trPrev; };
|
return trPrev; };
|
||||||
TTrack *Connected(int s, double &d) const;
|
TTrack *Connected(int s, double &d) const;
|
||||||
bool SetConnections(int i);
|
bool SetConnections(int i);
|
||||||
bool Switch(int i, double t = -1.0, double d = -1.0);
|
bool Switch(int i, float const t = -1.f, float const d = -1.f);
|
||||||
bool SwitchForced(int i, TDynamicObject *o);
|
bool SwitchForced(int i, TDynamicObject *o);
|
||||||
int CrossSegment(int from, int into);
|
int CrossSegment(int from, int into);
|
||||||
inline int GetSwitchState() {
|
inline int GetSwitchState() {
|
||||||
@@ -215,7 +217,16 @@ public:
|
|||||||
SwitchExtension ?
|
SwitchExtension ?
|
||||||
SwitchExtension->CurrentIndex :
|
SwitchExtension->CurrentIndex :
|
||||||
-1); };
|
-1); };
|
||||||
void Load(cParser *parser, Math3D::vector3 pOrigin, std::string name);
|
// returns number of different routes possible to take from given point
|
||||||
|
// TODO: specify entry point, number of routes for switches can vary
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
RouteCount() const {
|
||||||
|
return (
|
||||||
|
SwitchExtension != nullptr ?
|
||||||
|
SwitchExtension->iRoads - 1 :
|
||||||
|
1 ); }
|
||||||
|
void Load(cParser *parser, Math3D::vector3 pOrigin);
|
||||||
bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
||||||
bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
||||||
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
|
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
|
||||||
@@ -223,14 +234,21 @@ public:
|
|||||||
bool AddDynamicObject(TDynamicObject *Dynamic);
|
bool AddDynamicObject(TDynamicObject *Dynamic);
|
||||||
bool RemoveDynamicObject(TDynamicObject *Dynamic);
|
bool RemoveDynamicObject(TDynamicObject *Dynamic);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
void create_geometry( geometrybank_handle const &Bank ); // wypełnianie VBO
|
void create_geometry( geometrybank_handle const &Bank ); // wypełnianie VBO
|
||||||
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
|
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
|
||||||
|
|
||||||
void RaOwnerSet(TSubRect *o) {
|
void RaOwnerSet( scene::basic_cell *o ) {
|
||||||
if (SwitchExtension)
|
if( SwitchExtension ) { SwitchExtension->pOwner = o; } };
|
||||||
SwitchExtension->pOwner = o; };
|
|
||||||
bool InMovement(); // czy w trakcie animacji?
|
bool InMovement(); // czy w trakcie animacji?
|
||||||
void RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined);
|
void RaAssign( TAnimModel *am, TEvent *done, TEvent *joined );
|
||||||
void RaAnimListAdd(TTrack *t);
|
void RaAnimListAdd(TTrack *t);
|
||||||
TTrack * RaAnimate();
|
TTrack * RaAnimate();
|
||||||
|
|
||||||
@@ -241,22 +259,42 @@ public:
|
|||||||
std::string IsolatedName();
|
std::string IsolatedName();
|
||||||
bool IsolatedEventsAssign(TEvent *busy, TEvent *free);
|
bool IsolatedEventsAssign(TEvent *busy, TEvent *free);
|
||||||
double WidthTotal();
|
double WidthTotal();
|
||||||
GLuint TextureGet(int i) {
|
|
||||||
return (
|
|
||||||
i ?
|
|
||||||
m_material1 :
|
|
||||||
m_material2 ); };
|
|
||||||
bool IsGroupable();
|
bool IsGroupable();
|
||||||
int TestPoint( Math3D::vector3 *Point);
|
int TestPoint( Math3D::vector3 *Point);
|
||||||
void MovedUp1(float const dh);
|
void MovedUp1(float const dh);
|
||||||
std::string NameGet();
|
|
||||||
void VelocitySet(float v);
|
void VelocitySet(float v);
|
||||||
float VelocityGet();
|
double VelocityGet();
|
||||||
void ConnectionsLog();
|
void ConnectionsLog();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// calculates path's bounding radius
|
||||||
|
void
|
||||||
|
radius_();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnvironmentSet();
|
void EnvironmentSet();
|
||||||
void EnvironmentReset();
|
void EnvironmentReset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// collection of virtual tracks and roads present in the scene
|
||||||
|
class path_table : public basic_table<TTrack> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
~path_table();
|
||||||
|
// legacy method, initializes tracks after deserialization from scenario file
|
||||||
|
void
|
||||||
|
InitTracks();
|
||||||
|
// legacy method, sends list of occupied paths over network
|
||||||
|
void
|
||||||
|
TrackBusyList() const;
|
||||||
|
// legacy method, sends list of occupied path sections over network
|
||||||
|
void
|
||||||
|
IsolatedBusyList() const;
|
||||||
|
// legacy method, sends state of specified path section over network
|
||||||
|
void
|
||||||
|
IsolatedBusy( std::string const &Name ) const;
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
585
Traction.cpp
585
Traction.cpp
@@ -14,10 +14,10 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Traction.h"
|
#include "Traction.h"
|
||||||
|
|
||||||
|
#include "simulation.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "mctools.h"
|
|
||||||
#include "TractionPower.h"
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
/*
|
/*
|
||||||
@@ -90,9 +90,97 @@ jawnie nazwę sekcji, ewentualnie nazwę zasilacza (zostanie zastąpiona wskazan
|
|||||||
sekcji z sąsiedniego przęsła).
|
sekcji z sąsiedniego przęsła).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::size_t
|
TTraction::TTraction( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||||
TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ) {
|
// legacy constructor
|
||||||
|
TTraction::TTraction( std::string Name ) {
|
||||||
|
|
||||||
|
m_name = Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::dvec3 LoadPoint( cParser &Input ) {
|
||||||
|
// pobranie współrzędnych punktu
|
||||||
|
glm::dvec3 point;
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> point.x
|
||||||
|
>> point.y
|
||||||
|
>> point.z;
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TTraction::Load( cParser *parser, glm::dvec3 const &pOrigin ) {
|
||||||
|
|
||||||
|
parser->getTokens( 4 );
|
||||||
|
*parser
|
||||||
|
>> asPowerSupplyName
|
||||||
|
>> NominalVoltage
|
||||||
|
>> MaxCurrent
|
||||||
|
>> fResistivity;
|
||||||
|
if( fResistivity == 0.01f ) {
|
||||||
|
// tyle jest w sceneriach [om/km]
|
||||||
|
// taka sensowniejsza wartość za http://www.ikolej.pl/fileadmin/user_upload/Seminaria_IK/13_05_07_Prezentacja_Kruczek.pdf
|
||||||
|
fResistivity = 0.075f;
|
||||||
|
}
|
||||||
|
fResistivity *= 0.001f; // teraz [om/m]
|
||||||
|
// Ra 2014-02: a tutaj damy symbol sieci i jej budowę, np.:
|
||||||
|
// SKB70-C, CuCd70-2C, KB95-2C, C95-C, C95-2C, YC95-2C, YpC95-2C, YC120-2C
|
||||||
|
// YpC120-2C, YzC120-2C, YwsC120-2C, YC150-C150, YC150-2C150, C150-C150
|
||||||
|
// C120-2C, 2C120-2C, 2C120-2C-1, 2C120-2C-2, 2C120-2C-3, 2C120-2C-4
|
||||||
|
auto const material = parser->getToken<std::string>();
|
||||||
|
// 1=miedziana, rysuje się na zielono albo czerwono
|
||||||
|
// 2=aluminiowa, rysuje się na czarno
|
||||||
|
if( material == "none" ) { Material = 0; }
|
||||||
|
else if( material == "al" ) { Material = 2; }
|
||||||
|
else { Material = 1; }
|
||||||
|
parser->getTokens( 2 );
|
||||||
|
*parser
|
||||||
|
>> WireThickness
|
||||||
|
>> DamageFlag;
|
||||||
|
pPoint1 = LoadPoint( *parser ) + pOrigin;
|
||||||
|
pPoint2 = LoadPoint( *parser ) + pOrigin;
|
||||||
|
pPoint3 = LoadPoint( *parser ) + pOrigin;
|
||||||
|
pPoint4 = LoadPoint( *parser ) + pOrigin;
|
||||||
|
auto const minheight { parser->getToken<double>() };
|
||||||
|
fHeightDifference = ( pPoint3.y - pPoint1.y + pPoint4.y - pPoint2.y ) * 0.5 - minheight;
|
||||||
|
auto const segmentlength { parser->getToken<double>() };
|
||||||
|
iNumSections = (
|
||||||
|
segmentlength ?
|
||||||
|
glm::length( ( pPoint1 - pPoint2 ) ) / segmentlength :
|
||||||
|
0 );
|
||||||
|
parser->getTokens( 2 );
|
||||||
|
*parser
|
||||||
|
>> Wires
|
||||||
|
>> WireOffset;
|
||||||
|
m_visible = ( parser->getToken<std::string>() == "vis" );
|
||||||
|
|
||||||
|
std::string token { parser->getToken<std::string>() };
|
||||||
|
if( token == "parallel" ) {
|
||||||
|
// jawne wskazanie innego przęsła, na które może przestawić się pantograf
|
||||||
|
parser->getTokens();
|
||||||
|
*parser >> asParallel;
|
||||||
|
}
|
||||||
|
while( ( false == token.empty() )
|
||||||
|
&& ( token != "endtraction" ) ) {
|
||||||
|
|
||||||
|
token = parser->getToken<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Init(); // przeliczenie parametrów
|
||||||
|
|
||||||
|
// calculate traction location
|
||||||
|
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
|
||||||
|
TTraction::create_geometry( geometrybank_handle const &Bank ) {
|
||||||
if( m_geometry != null_handle ) {
|
if( m_geometry != null_handle ) {
|
||||||
return GfxRenderer.Vertices( m_geometry ).size() / 2;
|
return GfxRenderer.Vertices( m_geometry ).size() / 2;
|
||||||
}
|
}
|
||||||
@@ -106,14 +194,14 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
basic_vertex startvertex, endvertex;
|
basic_vertex startvertex, endvertex;
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x,
|
pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - m_origin.x,
|
||||||
pPoint1.y - Origin.y,
|
pPoint1.y - m_origin.y,
|
||||||
pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z );
|
pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - m_origin.z );
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x,
|
pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - m_origin.x,
|
||||||
pPoint2.y - Origin.y,
|
pPoint2.y - m_origin.y,
|
||||||
pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z );
|
pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
// Nie wiem co 'Marcin
|
// Nie wiem co 'Marcin
|
||||||
@@ -130,9 +218,9 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
if( Wires > 1 ) { // lina nośna w kawałkach
|
if( Wires > 1 ) { // lina nośna w kawałkach
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint3.x - Origin.x,
|
pPoint3.x - m_origin.x,
|
||||||
pPoint3.y - Origin.y,
|
pPoint3.y - m_origin.y,
|
||||||
pPoint3.z - Origin.z );
|
pPoint3.z - m_origin.z );
|
||||||
for( int i = 0; i < iNumSections - 1; ++i ) {
|
for( int i = 0; i < iNumSections - 1; ++i ) {
|
||||||
pt3 = pPoint3 + v1 * f;
|
pt3 = pPoint3 + v1 * f;
|
||||||
t = ( 1 - std::fabs( f - mid ) * 2 );
|
t = ( 1 - std::fabs( f - mid ) * 2 );
|
||||||
@@ -141,9 +229,9 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
&& ( i != iNumSections - 2 ) ) ) {
|
&& ( i != iNumSections - 2 ) ) ) {
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt3.x - Origin.x,
|
pt3.x - m_origin.x,
|
||||||
pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y,
|
pt3.y - std::sqrt( t ) * fHeightDifference - m_origin.y,
|
||||||
pt3.z - Origin.z );
|
pt3.z - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
startvertex = endvertex;
|
startvertex = endvertex;
|
||||||
@@ -152,9 +240,9 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
}
|
}
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint4.x - Origin.x,
|
pPoint4.x - m_origin.x,
|
||||||
pPoint4.y - Origin.y,
|
pPoint4.y - m_origin.y,
|
||||||
pPoint4.z - Origin.z );
|
pPoint4.z - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
}
|
}
|
||||||
@@ -162,14 +250,14 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
if( Wires > 2 ) {
|
if( Wires > 2 ) {
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint1.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x,
|
pPoint1.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - m_origin.x,
|
||||||
pPoint1.y - Origin.y,
|
pPoint1.y - m_origin.y,
|
||||||
pPoint1.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z );
|
pPoint1.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - m_origin.z );
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint2.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x,
|
pPoint2.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - m_origin.x,
|
||||||
pPoint2.y - Origin.y,
|
pPoint2.y - m_origin.y,
|
||||||
pPoint2.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z );
|
pPoint2.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
}
|
}
|
||||||
@@ -179,22 +267,22 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
if( Wires == 4 ) {
|
if( Wires == 4 ) {
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint3.x - Origin.x,
|
pPoint3.x - m_origin.x,
|
||||||
pPoint3.y - 0.65f * fHeightDifference - Origin.y,
|
pPoint3.y - 0.65f * fHeightDifference - m_origin.y,
|
||||||
pPoint3.z - Origin.z );
|
pPoint3.z - m_origin.z );
|
||||||
for( int i = 0; i < iNumSections - 1; ++i ) {
|
for( int i = 0; i < iNumSections - 1; ++i ) {
|
||||||
pt3 = pPoint3 + v1 * f;
|
pt3 = pPoint3 + v1 * f;
|
||||||
t = ( 1 - std::fabs( f - mid ) * 2 );
|
t = ( 1 - std::fabs( f - mid ) * 2 );
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt3.x - Origin.x,
|
pt3.x - m_origin.x,
|
||||||
pt3.y - std::sqrt( t ) * fHeightDifference - (
|
pt3.y - std::sqrt( t ) * fHeightDifference - (
|
||||||
( ( i == 0 )
|
( ( i == 0 )
|
||||||
|| ( i == iNumSections - 2 ) ) ?
|
|| ( i == iNumSections - 2 ) ) ?
|
||||||
0.25f * fHeightDifference :
|
0.25f * fHeightDifference :
|
||||||
0.05 )
|
0.05 )
|
||||||
- Origin.y,
|
- m_origin.y,
|
||||||
pt3.z - Origin.z );
|
pt3.z - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
startvertex = endvertex;
|
startvertex = endvertex;
|
||||||
@@ -202,9 +290,9 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
}
|
}
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pPoint4.x - Origin.x,
|
pPoint4.x - m_origin.x,
|
||||||
pPoint4.y - 0.65f * fHeightDifference - Origin.y,
|
pPoint4.y - 0.65f * fHeightDifference - m_origin.y,
|
||||||
pPoint4.z - Origin.z );
|
pPoint4.z - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
}
|
}
|
||||||
@@ -223,28 +311,28 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
if( ( i % 2 ) == 0 ) {
|
if( ( i % 2 ) == 0 ) {
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt3.x - Origin.x,
|
pt3.x - m_origin.x,
|
||||||
pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y,
|
pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - m_origin.y,
|
||||||
pt3.z - Origin.z );
|
pt3.z - m_origin.z );
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x,
|
pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - m_origin.x,
|
||||||
pt4.y - Origin.y,
|
pt4.y - m_origin.y,
|
||||||
pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z );
|
pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt3.x - Origin.x,
|
pt3.x - m_origin.x,
|
||||||
pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y,
|
pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - m_origin.y,
|
||||||
pt3.z - Origin.z );
|
pt3.z - m_origin.z );
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x,
|
pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - m_origin.x,
|
||||||
pt4.y - Origin.y,
|
pt4.y - m_origin.y,
|
||||||
pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z );
|
pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
}
|
}
|
||||||
@@ -253,14 +341,14 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
|| ( i == iNumSections - 3 ) ) ) ) {
|
|| ( i == iNumSections - 3 ) ) ) ) {
|
||||||
startvertex.position =
|
startvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt3.x - Origin.x,
|
pt3.x - m_origin.x,
|
||||||
pt3.y - std::sqrt( t ) * fHeightDifference - 0.05 - Origin.y,
|
pt3.y - std::sqrt( t ) * fHeightDifference - 0.05 - m_origin.y,
|
||||||
pt3.z - Origin.z );
|
pt3.z - m_origin.z );
|
||||||
endvertex.position =
|
endvertex.position =
|
||||||
glm::vec3(
|
glm::vec3(
|
||||||
pt3.x - Origin.x,
|
pt3.x - m_origin.x,
|
||||||
pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y,
|
pt3.y - std::sqrt( t ) * fHeightDifference - m_origin.y,
|
||||||
pt3.z - Origin.z );
|
pt3.z - m_origin.z );
|
||||||
vertices.emplace_back( startvertex );
|
vertices.emplace_back( startvertex );
|
||||||
vertices.emplace_back( endvertex );
|
vertices.emplace_back( endvertex );
|
||||||
}
|
}
|
||||||
@@ -276,55 +364,59 @@ TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &O
|
|||||||
|
|
||||||
int TTraction::TestPoint(glm::dvec3 const &Point)
|
int TTraction::TestPoint(glm::dvec3 const &Point)
|
||||||
{ // sprawdzanie, czy przęsła można połączyć
|
{ // sprawdzanie, czy przęsła można połączyć
|
||||||
if (!hvNext[0])
|
if( ( hvNext[ 0 ] == nullptr )
|
||||||
if( glm::all( glm::epsilonEqual( Point, pPoint1, 0.025 ) ) )
|
&& ( glm::all( glm::epsilonEqual( Point, pPoint1, 0.025 ) ) ) ) {
|
||||||
return 0;
|
return 0;
|
||||||
if (!hvNext[1])
|
}
|
||||||
if( glm::all( glm::epsilonEqual( Point, pPoint2, 0.025 ) ) )
|
if( ( hvNext[ 1 ] == nullptr )
|
||||||
|
&& ( glm::all( glm::epsilonEqual( Point, pPoint2, 0.025 ) ) ) ) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TTraction::Connect(int my, TTraction *with, int to)
|
//łączenie segmentu (with) od strony (my) do jego (to)
|
||||||
{ //łączenie segmentu (with) od strony (my) do jego (to)
|
void
|
||||||
if (my)
|
TTraction::Connect(int my, TTraction *with, int to) {
|
||||||
{ // do mojego Point2
|
|
||||||
hvNext[1] = with;
|
|
||||||
iNext[1] = to;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // do mojego Point1
|
|
||||||
hvNext[0] = with;
|
|
||||||
iNext[0] = to;
|
|
||||||
}
|
|
||||||
if (to)
|
|
||||||
{ // do jego Point2
|
|
||||||
with->hvNext[1] = this;
|
|
||||||
with->iNext[1] = my;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // do jego Point1
|
|
||||||
with->hvNext[0] = this;
|
|
||||||
with->iNext[0] = my;
|
|
||||||
}
|
|
||||||
if (hvNext[0]) // jeśli z obu stron podłączony
|
|
||||||
if (hvNext[1])
|
|
||||||
iLast = 0; // to nie jest ostatnim
|
|
||||||
if (with->hvNext[0]) // temu też, bo drugi raz łączenie się nie nie wykona
|
|
||||||
if (with->hvNext[1])
|
|
||||||
with->iLast = 0; // to nie jest ostatnim
|
|
||||||
};
|
|
||||||
|
|
||||||
bool TTraction::WhereIs()
|
hvNext[ my ] = with;
|
||||||
{ // ustalenie przedostatnich przęseł
|
iNext[ my ] = to;
|
||||||
if (iLast)
|
|
||||||
return (iLast == 1); // ma już ustaloną informację o położeniu
|
if( ( hvNext[ 0 ] != nullptr )
|
||||||
if (hvNext[0] ? hvNext[0]->iLast == 1 : false) // jeśli poprzedni jest ostatnim
|
&& ( hvNext[ 1 ] != nullptr ) ) {
|
||||||
iLast = 2; // jest przedostatnim
|
// jeśli z obu stron podłączony to nie jest ostatnim
|
||||||
else if (hvNext[1] ? hvNext[1]->iLast == 1 : false) // jeśli następny jest ostatnim
|
iLast = 0;
|
||||||
iLast = 2; // jest przedostatnim
|
}
|
||||||
return (iLast == 1); // ostatnie będą dostawać zasilanie
|
|
||||||
};
|
with->hvNext[ to ] = this;
|
||||||
|
with->iNext[ to ] = my;
|
||||||
|
|
||||||
|
if( ( with->hvNext[ 0 ] != nullptr )
|
||||||
|
&& ( with->hvNext[ 1 ] != nullptr ) ) {
|
||||||
|
// temu też, bo drugi raz łączenie się nie nie wykona
|
||||||
|
with->iLast = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ustalenie przedostatnich przęseł
|
||||||
|
bool TTraction::WhereIs() {
|
||||||
|
|
||||||
|
if( iLast ) {
|
||||||
|
// ma już ustaloną informację o położeniu
|
||||||
|
return ( iLast & 1 );
|
||||||
|
}
|
||||||
|
for( int endindex = 0; endindex < 2; ++endindex ) {
|
||||||
|
if( hvNext[ endindex ] == nullptr ) {
|
||||||
|
// no neighbour piece means this one is last
|
||||||
|
iLast |= 1;
|
||||||
|
}
|
||||||
|
else if( hvNext[ endindex ]->hvNext[ 1 - iNext[ endindex ] ] == nullptr ) {
|
||||||
|
// otherwise if that neighbour has no further connection on the opposite end then this piece is second-last
|
||||||
|
iLast |= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (iLast & 1); // ostatnie będą dostawać zasilanie
|
||||||
|
}
|
||||||
|
|
||||||
void TTraction::Init()
|
void TTraction::Init()
|
||||||
{ // przeliczenie parametrów
|
{ // przeliczenie parametrów
|
||||||
@@ -441,6 +533,18 @@ double TTraction::VoltageGet(double u, double i)
|
|||||||
return 0.0; // gdy nie podłączony wcale?
|
return 0.0; // gdy nie podłączony wcale?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// calculates path's bounding radius
|
||||||
|
void
|
||||||
|
TTraction::radius_() {
|
||||||
|
|
||||||
|
auto const points = endpoints();
|
||||||
|
for( auto &point : points ) {
|
||||||
|
m_area.radius = std::max(
|
||||||
|
m_area.radius,
|
||||||
|
static_cast<float>( glm::length( m_area.center - point ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3
|
glm::vec3
|
||||||
TTraction::wire_color() const {
|
TTraction::wire_color() const {
|
||||||
|
|
||||||
@@ -488,30 +592,41 @@ TTraction::wire_color() const {
|
|||||||
|
|
||||||
case 1: {
|
case 1: {
|
||||||
// czerwone z podłączonym zasilaniem 1
|
// czerwone z podłączonym zasilaniem 1
|
||||||
color.r = 1.0f;
|
// color.r = 1.0f;
|
||||||
color.g = 0.0f;
|
// color.g = 0.0f;
|
||||||
color.b = 0.0f;
|
// color.b = 0.0f;
|
||||||
|
// cyan
|
||||||
|
color = glm::vec3 { 0.f, 174.f / 255.f, 239.f / 255.f };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
// zielone z podłączonym zasilaniem 2
|
// zielone z podłączonym zasilaniem 2
|
||||||
color.r = 0.0f;
|
// color.r = 0.0f;
|
||||||
color.g = 1.0f;
|
// color.g = 1.0f;
|
||||||
color.b = 0.0f;
|
// color.b = 0.0f;
|
||||||
|
// yellow
|
||||||
|
color = glm::vec3 { 240.f / 255.f, 228.f / 255.f, 0.f };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
//żółte z podłączonym zasilaniem z obu stron
|
//żółte z podłączonym zasilaniem z obu stron
|
||||||
color.r = 1.0f;
|
// color.r = 1.0f;
|
||||||
color.g = 1.0f;
|
// color.g = 1.0f;
|
||||||
color.b = 0.0f;
|
// color.b = 0.0f;
|
||||||
|
// green
|
||||||
|
color = glm::vec3 { 0.f, 239.f / 255.f, 118.f / 255.f };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
// niebieskie z podłączonym zasilaniem
|
// niebieskie z podłączonym zasilaniem
|
||||||
color.r = 0.5f;
|
// color.r = 0.5f;
|
||||||
color.g = 0.5f;
|
// color.g = 0.5f;
|
||||||
color.b = 1.0f;
|
// color.b = 1.0f;
|
||||||
|
// white for powered, red for ends
|
||||||
|
color = (
|
||||||
|
psPowered != nullptr ?
|
||||||
|
glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f } :
|
||||||
|
glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f } );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: { break; }
|
default: { break; }
|
||||||
@@ -521,6 +636,262 @@ TTraction::wire_color() const {
|
|||||||
color.g *= 0.6f;
|
color.g *= 0.6f;
|
||||||
color.b *= 0.6f;
|
color.b *= 0.6f;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
switch( iTries ) {
|
||||||
|
case 0: {
|
||||||
|
color = glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f }; // red
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
color = glm::vec3{ 240.f / 255.f, 228.f / 255.f, 0.f }; // yellow
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
color = glm::vec3{ 0.f / 255.f, 239.f / 255.f, 118.f / 255.f }; // green
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
color = glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
switch( iLast ) {
|
||||||
|
case 0: {
|
||||||
|
color = glm::vec3{ 240.f / 255.f, 228.f / 255.f, 0.f }; // yellow
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
color = glm::vec3{ 239.f / 255.f, 128.f / 255.f, 128.f / 255.f }; // red
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
color = glm::vec3{ 0.f / 255.f, 239.f / 255.f, 118.f / 255.f }; // green
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
color = glm::vec3{ 239.f / 255.f, 239.f / 255.f, 239.f / 255.f };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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 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
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EU07_IGNORE_LEGACYPROCESSINGORDER
|
||||||
|
for( auto *traction : m_items ) {
|
||||||
|
#else
|
||||||
|
// NOTE: legacy code peformed item operations last-to-first due to way the items were added to the list
|
||||||
|
// this had impact in situations like two possible connection candidates, where only the first one would be used
|
||||||
|
for( auto first = std::rbegin(m_items); first != std::rend(m_items); ++first ) {
|
||||||
|
auto *traction = *first;
|
||||||
|
#endif
|
||||||
|
if( traction->hvNext[ 0 ] == nullptr ) {
|
||||||
|
// tylko jeśli jeszcze nie podłączony
|
||||||
|
std::tie( matchingtraction, connection ) = simulation::Region->find_traction( traction->pPoint1, traction );
|
||||||
|
switch (connection) {
|
||||||
|
case 0:
|
||||||
|
case 1: {
|
||||||
|
traction->Connect( 0, matchingtraction, connection );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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 ] == nullptr ) {
|
||||||
|
// tylko jeśli jeszcze nie podłączony
|
||||||
|
std::tie( matchingtraction, connection ) = simulation::Region->find_traction( traction->pPoint2, traction );
|
||||||
|
switch (connection) {
|
||||||
|
case 0:
|
||||||
|
case 1: {
|
||||||
|
traction->Connect( 1, matchingtraction, connection );
|
||||||
|
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 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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() ) {
|
||||||
|
// true for outer pieces of the traction section
|
||||||
|
traction->iTries = 5; // oznaczanie końcowych
|
||||||
|
++endcount;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TTraction *> ends; ends.reserve( endcount );
|
||||||
|
for( auto *traction : m_items ) {
|
||||||
|
//łączenie bieżni wspólnych, w tym oznaczanie niepodanych jawnie
|
||||||
|
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 == nullptr ) {
|
||||||
|
// jeśli jeszcze nie został włączony w kółko
|
||||||
|
auto *nTemp = find( traction->asParallel );
|
||||||
|
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
|
||||||
|
traction->hvParallel = nTemp->hvParallel; // przjąć dotychczasowy wskaźnik od niego
|
||||||
|
}
|
||||||
|
nTemp->hvParallel = traction; // i na koniec ustawienie wskaźnika zwrotnego
|
||||||
|
}
|
||||||
|
if( traction->hvParallel == nullptr ) {
|
||||||
|
ErrorLog( "Missed overhead: " + traction->asParallel ); // logowanie braku
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( traction->iTries == 5 ) {
|
||||||
|
// jeśli zaznaczony do podłączenia
|
||||||
|
// wypełnianie tabeli końców w celu szukania im połączeń
|
||||||
|
ends.emplace_back( traction );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// gdy koniec jest samotny, to na razie nie zostanie podłączony (nie powinno takich być)
|
||||||
|
end = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while( true == connected );
|
||||||
|
}
|
||||||
|
|||||||
51
Traction.h
51
Traction.h
@@ -10,14 +10,17 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "GL/glew.h"
|
|
||||||
#include "dumb3d.h"
|
#include "scenenode.h"
|
||||||
#include "openglgeometrybank.h"
|
#include "Segment.h"
|
||||||
|
#include "material.h"
|
||||||
|
#include "Names.h"
|
||||||
|
#include "Model3d.h"
|
||||||
|
|
||||||
class TTractionPowerSource;
|
class TTractionPowerSource;
|
||||||
|
|
||||||
class TTraction
|
class TTraction : public editor::basic_node {
|
||||||
{ // drut zasilający, dla wskaźników używać przedrostka "hv"
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
public: // na razie
|
public: // na razie
|
||||||
@@ -25,11 +28,11 @@ class TTraction
|
|||||||
TTractionPowerSource *psPowered { nullptr }; // ustawione tylko dla bezpośrednio zasilanego przęsła
|
TTractionPowerSource *psPowered { nullptr }; // ustawione tylko dla bezpośrednio zasilanego przęsła
|
||||||
TTraction *hvNext[ 2 ] { nullptr, nullptr }; //łączenie drutów w sieć
|
TTraction *hvNext[ 2 ] { nullptr, nullptr }; //łączenie drutów w sieć
|
||||||
int iNext[ 2 ] { 0, 0 }; // do którego końca się łączy
|
int iNext[ 2 ] { 0, 0 }; // do którego końca się łączy
|
||||||
int iLast { 1 }; //że niby ostatni drut // ustawiony bit 0, jeśli jest ostatnim drutem w sekcji; bit1 - przedostatni
|
int iLast { 0 }; //że niby ostatni drut // ustawiony bit 0, jeśli jest ostatnim drutem w sekcji; bit1 - przedostatni
|
||||||
public:
|
public:
|
||||||
glm::dvec3 pPoint1, pPoint2, pPoint3, pPoint4;
|
glm::dvec3 pPoint1, pPoint2, pPoint3, pPoint4;
|
||||||
glm::dvec3 vParametric; // współczynniki równania parametrycznego odcinka
|
glm::dvec3 vParametric; // współczynniki równania parametrycznego odcinka
|
||||||
double fHeightDifference { 0.0 }; //,fMiddleHeight;
|
double fHeightDifference { 0.0 };
|
||||||
int iNumSections { 0 };
|
int iNumSections { 0 };
|
||||||
float NominalVoltage { 0.0f };
|
float NominalVoltage { 0.0f };
|
||||||
float MaxCurrent { 0.0f };
|
float MaxCurrent { 0.0f };
|
||||||
@@ -44,14 +47,27 @@ class TTraction
|
|||||||
std::string asParallel; // nazwa przęsła, z którym może być bieżnia wspólna
|
std::string asParallel; // nazwa przęsła, z którym może być bieżnia wspólna
|
||||||
TTraction *hvParallel { nullptr }; // jednokierunkowa i zapętlona lista przęseł ewentualnej bieżni wspólnej
|
TTraction *hvParallel { nullptr }; // jednokierunkowa i zapętlona lista przęseł ewentualnej bieżni wspólnej
|
||||||
float fResistance[ 2 ] { -1.0f, -1.0f }; // rezystancja zastępcza do punktu zasilania (0: przęsło zasilane, <0: do policzenia)
|
float fResistance[ 2 ] { -1.0f, -1.0f }; // rezystancja zastępcza do punktu zasilania (0: przęsło zasilane, <0: do policzenia)
|
||||||
int iTries { 0 };
|
int iTries { 1 }; // 0 is used later down the road to mark directly powered pieces
|
||||||
int PowerState { 0 }; // type of incoming power, if any
|
int PowerState { 0 }; // type of incoming power, if any
|
||||||
// visualization data
|
// visualization data
|
||||||
|
glm::dvec3 m_origin;
|
||||||
geometry_handle m_geometry;
|
geometry_handle m_geometry;
|
||||||
|
|
||||||
|
TTraction( scene::node_data const &Nodedata );
|
||||||
|
// legacy constructor
|
||||||
|
TTraction( std::string Name );
|
||||||
|
|
||||||
|
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
|
// 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
|
// NOTE: deleting nodes doesn't currently release geometry data owned by the node. TODO: implement erasing individual geometry chunks and banks
|
||||||
std::size_t create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin );
|
std::size_t create_geometry( geometrybank_handle const &Bank );
|
||||||
int TestPoint(glm::dvec3 const &Point);
|
int TestPoint(glm::dvec3 const &Point);
|
||||||
void Connect(int my, TTraction *with, int to);
|
void Connect(int my, TTraction *with, int to);
|
||||||
void Init();
|
void Init();
|
||||||
@@ -59,8 +75,25 @@ class TTraction
|
|||||||
void ResistanceCalc(int d = -1, double r = 0, TTractionPowerSource *ps = nullptr);
|
void ResistanceCalc(int d = -1, double r = 0, TTractionPowerSource *ps = nullptr);
|
||||||
void PowerSet(TTractionPowerSource *ps);
|
void PowerSet(TTractionPowerSource *ps);
|
||||||
double VoltageGet(double u, double i);
|
double VoltageGet(double u, double i);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// calculates piece's bounding radius
|
||||||
|
void
|
||||||
|
radius_();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 wire_color() const;
|
glm::vec3 wire_color() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// collection of virtual tracks and roads present in the scene
|
||||||
|
class traction_table : public basic_table<TTraction> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// legacy method, initializes traction after deserialization from scenario file
|
||||||
|
void
|
||||||
|
InitTraction();
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -15,19 +15,17 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "TractionPower.h"
|
#include "TractionPower.h"
|
||||||
|
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "Ground.h"
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
TTractionPowerSource::TTractionPowerSource(TGroundNode const *node) :
|
TTractionPowerSource::TTractionPowerSource( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||||
gMyNode( node )
|
// legacy constructor
|
||||||
{
|
TTractionPowerSource::TTractionPowerSource( std::string Name ) {
|
||||||
psNode[0] = nullptr; // sekcje zostaną podłączone do zasilaczy
|
|
||||||
psNode[1] = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
TTractionPowerSource::~TTractionPowerSource(){};
|
m_name = Name;
|
||||||
|
}
|
||||||
|
|
||||||
void TTractionPowerSource::Init(double const u, double const i)
|
void TTractionPowerSource::Init(double const u, double const i)
|
||||||
{ // ustawianie zasilacza przy braku w scenerii
|
{ // ustawianie zasilacza przy braku w scenerii
|
||||||
@@ -36,61 +34,62 @@ void TTractionPowerSource::Init(double const u, double const i)
|
|||||||
MaxOutputCurrent = i;
|
MaxOutputCurrent = i;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TTractionPowerSource::Load(cParser *parser)
|
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::Render()
|
parser->getTokens( 10, false );
|
||||||
{
|
*parser
|
||||||
|
>> m_area.center.x
|
||||||
|
>> m_area.center.y
|
||||||
|
>> m_area.center.z
|
||||||
|
>> 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;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TTractionPowerSource::Update(double dt)
|
bool TTractionPowerSource::Update(double dt)
|
||||||
{ // powinno być wykonane raz na krok fizyki
|
{ // powinno być wykonane raz na krok fizyki
|
||||||
// if (NominalVoltage * TotalPreviousAdmitance >
|
// iloczyn napięcia i admitancji daje prąd
|
||||||
// MaxOutputCurrent * 0.00000005) // iloczyn napięcia i admitancji daje prąd
|
if (NominalVoltage * TotalPreviousAdmitance > MaxOutputCurrent) {
|
||||||
// ErrorLog("Power overload: \"" + gMyNode->asName + "\" with current " + AnsiString(NominalVoltage * TotalPreviousAdmitance) + "A");
|
|
||||||
if (NominalVoltage * TotalPreviousAdmitance >
|
|
||||||
MaxOutputCurrent) // iloczyn napięcia i admitancji daje prąd
|
|
||||||
{
|
|
||||||
FastFuse = true;
|
FastFuse = true;
|
||||||
FuseCounter += 1;
|
FuseCounter += 1;
|
||||||
if (FuseCounter > FastFuseRepetition)
|
if (FuseCounter > FastFuseRepetition) {
|
||||||
{
|
|
||||||
SlowFuse = true;
|
SlowFuse = true;
|
||||||
ErrorLog("Power overload: \"" + gMyNode->asName + "\" disabled for " +
|
ErrorLog( "Power overload: \"" + m_name + "\" disabled for " + std::to_string( SlowFuseTimeOut ) + "s" );
|
||||||
std::to_string(SlowFuseTimeOut) + "s");
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
ErrorLog("Power overload: \"" + gMyNode->asName + "\" disabled for " +
|
ErrorLog( "Power overload: \"" + m_name + "\" disabled for " + std::to_string( FastFuseTimeOut ) + "s" );
|
||||||
std::to_string(FastFuseTimeOut) + "s");
|
}
|
||||||
|
|
||||||
FuseTimer = 0;
|
FuseTimer = 0;
|
||||||
}
|
}
|
||||||
if (FastFuse || SlowFuse)
|
if (FastFuse || SlowFuse)
|
||||||
@@ -145,4 +144,15 @@ void TTractionPowerSource::PowerSet(TTractionPowerSource *ps)
|
|||||||
// else ErrorLog("nie może być więcej punktów zasilania niż dwa");
|
// 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/.
|
http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TractionPowerH
|
#pragma once
|
||||||
#define TractionPowerH
|
|
||||||
|
#include "scenenode.h"
|
||||||
#include "parser.h" //Tolaris-010603
|
#include "parser.h" //Tolaris-010603
|
||||||
|
#include "Names.h"
|
||||||
|
|
||||||
class TGroundNode;
|
class TTractionPowerSource : public editor::basic_node {
|
||||||
|
|
||||||
class TTractionPowerSource
|
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
double NominalVoltage = 0.0;
|
double NominalVoltage = 0.0;
|
||||||
double VoltageFrequency = 0.0;
|
double VoltageFrequency = 0.0;
|
||||||
@@ -33,27 +33,34 @@ class TTractionPowerSource
|
|||||||
bool SlowFuse = false;
|
bool SlowFuse = false;
|
||||||
double FuseTimer = 0.0;
|
double FuseTimer = 0.0;
|
||||||
int FuseCounter = 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:
|
public:
|
||||||
// AnsiString asName;
|
// zmienne publiczne
|
||||||
TTractionPowerSource(TGroundNode const *node);
|
TTractionPowerSource *psNode[ 2 ] = { nullptr, nullptr }; // zasilanie na końcach dla sekcji
|
||||||
~TTractionPowerSource();
|
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);
|
void Init(double const u, double const i);
|
||||||
bool Load(cParser *parser);
|
bool Load(cParser *parser);
|
||||||
bool Render();
|
|
||||||
bool Update(double dt);
|
bool Update(double dt);
|
||||||
double CurrentGet(double res);
|
double CurrentGet(double res);
|
||||||
void VoltageSet(double const v)
|
void VoltageSet(double const v) {
|
||||||
{
|
NominalVoltage = v; };
|
||||||
NominalVoltage = v;
|
|
||||||
};
|
|
||||||
void PowerSet(TTractionPowerSource *ps);
|
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
|
|
||||||
|
|||||||
46
Train.cpp
46
Train.cpp
@@ -360,11 +360,6 @@ TTrain::TTrain() {
|
|||||||
|
|
||||||
TTrain::~TTrain()
|
TTrain::~TTrain()
|
||||||
{
|
{
|
||||||
if (DynamicObject)
|
|
||||||
if (DynamicObject->Mechanik)
|
|
||||||
DynamicObject->Mechanik->TakeControl(
|
|
||||||
true); // likwidacja kabiny wymaga przejęcia przez AI
|
|
||||||
|
|
||||||
sound_man->destroy_sound(&dsbNastawnikJazdy);
|
sound_man->destroy_sound(&dsbNastawnikJazdy);
|
||||||
sound_man->destroy_sound(&dsbNastawnikBocz);
|
sound_man->destroy_sound(&dsbNastawnikBocz);
|
||||||
sound_man->destroy_sound(&dsbRelay);
|
sound_man->destroy_sound(&dsbRelay);
|
||||||
@@ -515,11 +510,13 @@ PyObject *TTrain::GetTrainState() {
|
|||||||
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
|
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
|
||||||
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
|
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
|
||||||
PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) );
|
PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) );
|
||||||
|
PyDict_SetItemString( dict, "sanding", PyGetBool( mover->SandDose ));
|
||||||
// electric current data
|
// electric current data
|
||||||
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mover->RunningTraction.TractionVoltage ) );
|
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mover->RunningTraction.TractionVoltage ) );
|
||||||
PyDict_SetItemString( dict, "voltage", PyGetFloat( mover->Voltage ) );
|
PyDict_SetItemString( dict, "voltage", PyGetFloat( mover->Voltage ) );
|
||||||
PyDict_SetItemString( dict, "im", PyGetFloat( mover->Im ) );
|
PyDict_SetItemString( dict, "im", PyGetFloat( mover->Im ) );
|
||||||
PyDict_SetItemString( dict, "fuse", PyGetBool( mover->FuseFlag ) );
|
PyDict_SetItemString( dict, "fuse", PyGetBool( mover->FuseFlag ) );
|
||||||
|
PyDict_SetItemString( dict, "epfuse", PyGetBool( mover->EpFuse ));
|
||||||
// induction motor state data
|
// induction motor state data
|
||||||
const char* TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
|
const char* TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
|
||||||
const char* TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
|
const char* TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
|
||||||
@@ -559,6 +556,7 @@ PyObject *TTrain::GetTrainState() {
|
|||||||
PyDict_SetItemString( dict, ( std::string( "code_" ) + std::to_string( i + 1 ) ).c_str(), PyGetString( std::string( std::to_string( iUnits[ i ] ) +
|
PyDict_SetItemString( dict, ( std::string( "code_" ) + std::to_string( i + 1 ) ).c_str(), PyGetString( std::string( std::to_string( iUnits[ i ] ) +
|
||||||
cCode[ i ] ).c_str() ) );
|
cCode[ i ] ).c_str() ) );
|
||||||
PyDict_SetItemString( dict, ( std::string( "car_name" ) + std::to_string( i + 1 ) ).c_str(), PyGetString( asCarName[ i ].c_str() ) );
|
PyDict_SetItemString( dict, ( std::string( "car_name" ) + std::to_string( i + 1 ) ).c_str(), PyGetString( asCarName[ i ].c_str() ) );
|
||||||
|
PyDict_SetItemString( dict, ( std::string( "slip_" ) + std::to_string( i + 1 )).c_str(), PyGetBool( bSlip[i]) );
|
||||||
}
|
}
|
||||||
// ai state data
|
// ai state data
|
||||||
auto const &driver = DynamicObject->Mechanik;
|
auto const &driver = DynamicObject->Mechanik;
|
||||||
@@ -1630,7 +1628,7 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com
|
|||||||
// sound feedback, engine start for diesel vehicle
|
// sound feedback, engine start for diesel vehicle
|
||||||
Train->play_sound( Train->dsbDieselIgnition );
|
Train->play_sound( Train->dsbDieselIgnition );
|
||||||
// side-effects
|
// side-effects
|
||||||
Train->mvControlled->ConverterSwitch( Train->ggConverterButton.GetValue() > 0.5 );
|
Train->mvControlled->ConverterSwitch( ( Train->ggConverterButton.GetValue() > 0.5 ) || ( Train->mvControlled->ConverterStart == start::automatic ) );
|
||||||
Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 );
|
Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3414,6 +3412,20 @@ if
|
|||||||
d = d->Prev(); // w drugą stronę też
|
d = d->Prev(); // w drugą stronę też
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (cKey == GLFW_KEY_TAB)
|
||||||
|
{
|
||||||
|
while (d)
|
||||||
|
{
|
||||||
|
d->MoverParameters->V+= d->DirectionGet()*2.78;
|
||||||
|
d = d->Next(); // pozostałe też
|
||||||
|
}
|
||||||
|
d = DynamicObject->Prev();
|
||||||
|
while (d)
|
||||||
|
{
|
||||||
|
d->MoverParameters->V += d->DirectionGet()*2.78;
|
||||||
|
d = d->Prev(); // w drugą stronę też
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cKey == GLFW_KEY_MINUS)
|
if (cKey == GLFW_KEY_MINUS)
|
||||||
{ // zmniejszenie numeru kanału radiowego
|
{ // zmniejszenie numeru kanału radiowego
|
||||||
@@ -3697,21 +3709,22 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
bDoors[i][2] = (p->dDoorMoveL > 0.001);
|
bDoors[i][2] = (p->dDoorMoveL > 0.001);
|
||||||
iDoorNo[i] = p->iAnimType[ANIM_DOORS];
|
iDoorNo[i] = p->iAnimType[ANIM_DOORS];
|
||||||
iUnits[i] = iUnitNo;
|
iUnits[i] = iUnitNo;
|
||||||
cCode[i] = p->MoverParameters->TypeName[p->MoverParameters->TypeName.length()];
|
cCode[i] = p->MoverParameters->TypeName[p->MoverParameters->TypeName.length() - 1];
|
||||||
asCarName[i] = p->GetName();
|
asCarName[i] = p->name();
|
||||||
bPants[iUnitNo - 1][0] = (bPants[iUnitNo - 1][0] || p->MoverParameters->PantFrontUp);
|
bPants[iUnitNo - 1][0] = (bPants[iUnitNo - 1][0] || p->MoverParameters->PantFrontUp);
|
||||||
bPants[iUnitNo - 1][1] = (bPants[iUnitNo - 1][1] || p->MoverParameters->PantRearUp);
|
bPants[iUnitNo - 1][1] = (bPants[iUnitNo - 1][1] || p->MoverParameters->PantRearUp);
|
||||||
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow);
|
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow);
|
||||||
|
bSlip[i] = p->MoverParameters->SlippingWheels;
|
||||||
if (p->MoverParameters->CompressorSpeed > 0.00001)
|
if (p->MoverParameters->CompressorSpeed > 0.00001)
|
||||||
{
|
{
|
||||||
bComp[iUnitNo - 1][1] = (bComp[iUnitNo - 1][1] || p->MoverParameters->CompressorFlag);
|
bComp[iUnitNo - 1][1] = (bComp[iUnitNo - 1][1] || p->MoverParameters->CompressorFlag);
|
||||||
}
|
}
|
||||||
if ((in < 8) && (p->MoverParameters->eimc[eimc_p_Pmax] > 1))
|
if ((in < 8) && (p->MoverParameters->eimc[eimc_p_Pmax] > 1))
|
||||||
{
|
{
|
||||||
fEIMParams[1 + in][0] = p->MoverParameters->eimv[eimv_Fr];
|
fEIMParams[1 + in][0] = p->MoverParameters->eimv[eimv_Fmax];
|
||||||
fEIMParams[1 + in][1] = Max0R(fEIMParams[1 + in][0], 0);
|
fEIMParams[1 + in][1] = Max0R(fEIMParams[1 + in][0], 0);
|
||||||
fEIMParams[1 + in][2] = -Min0R(fEIMParams[1 + in][0], 0);
|
fEIMParams[1 + in][2] = -Min0R(fEIMParams[1 + in][0], 0);
|
||||||
fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fr] /
|
fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fmax] /
|
||||||
Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
|
Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
|
||||||
fEIMParams[1 + in][4] = Max0R(fEIMParams[1 + in][3], 0);
|
fEIMParams[1 + in][4] = Max0R(fEIMParams[1 + in][3], 0);
|
||||||
fEIMParams[1 + in][5] = -Min0R(fEIMParams[1 + in][3], 0);
|
fEIMParams[1 + in][5] = -Min0R(fEIMParams[1 + in][3], 0);
|
||||||
@@ -3743,6 +3756,7 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
bDoors[i][0] = false;
|
bDoors[i][0] = false;
|
||||||
bDoors[i][1] = false;
|
bDoors[i][1] = false;
|
||||||
bDoors[i][2] = false;
|
bDoors[i][2] = false;
|
||||||
|
bSlip[i] = false;
|
||||||
iUnits[i] = 0;
|
iUnits[i] = 0;
|
||||||
cCode[i] = 0; //'0';
|
cCode[i] = 0; //'0';
|
||||||
asCarName[i] = "";
|
asCarName[i] = "";
|
||||||
@@ -6385,7 +6399,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|||||||
}
|
}
|
||||||
else if (token == "pyscreen:")
|
else if (token == "pyscreen:")
|
||||||
{
|
{
|
||||||
pyScreens.init(*parser, DynamicObject->mdKabina, DynamicObject->GetName(),
|
pyScreens.init(*parser, DynamicObject->mdKabina, DynamicObject->name(),
|
||||||
NewCabNo);
|
NewCabNo);
|
||||||
}
|
}
|
||||||
// btLampkaUnknown.Init("unknown",mdKabina,false);
|
// btLampkaUnknown.Init("unknown",mdKabina,false);
|
||||||
@@ -6868,9 +6882,11 @@ void TTrain::set_cab_controls() {
|
|||||||
if( true == bCabLightDim ) {
|
if( true == bCabLightDim ) {
|
||||||
ggCabLightDimButton.PutValue( 1.0 );
|
ggCabLightDimButton.PutValue( 1.0 );
|
||||||
}
|
}
|
||||||
if( true == InstrumentLightActive ) {
|
|
||||||
ggInstrumentLightButton.PutValue( 1.0 );
|
ggInstrumentLightButton.PutValue( (
|
||||||
}
|
InstrumentLightActive ?
|
||||||
|
1.0 :
|
||||||
|
0.0 ) );
|
||||||
// doors
|
// doors
|
||||||
// NOTE: we're relying on the cab models to have switches reversed for the rear cab(?)
|
// NOTE: we're relying on the cab models to have switches reversed for the rear cab(?)
|
||||||
ggDoorLeftButton.PutValue( mvOccupied->DoorLeftOpened ? 1.0 : 0.0 );
|
ggDoorLeftButton.PutValue( mvOccupied->DoorLeftOpened ? 1.0 : 0.0 );
|
||||||
@@ -7168,7 +7184,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
|
|||||||
/*
|
/*
|
||||||
TGauge *gg { nullptr }; // roboczy wskaźnik na obiekt animujący gałkę
|
TGauge *gg { nullptr }; // roboczy wskaźnik na obiekt animujący gałkę
|
||||||
*/
|
*/
|
||||||
std::unordered_map<std::string, TGauge &> gauges = {
|
std::unordered_map<std::string, TGauge &> const gauges = {
|
||||||
{ "mainctrl:", ggMainCtrl },
|
{ "mainctrl:", ggMainCtrl },
|
||||||
{ "scndctrl:", ggScndCtrl },
|
{ "scndctrl:", ggScndCtrl },
|
||||||
{ "dirkey:" , ggDirKey },
|
{ "dirkey:" , ggDirKey },
|
||||||
|
|||||||
3
Train.h
3
Train.h
@@ -72,6 +72,8 @@ public:
|
|||||||
|
|
||||||
class TTrain
|
class TTrain
|
||||||
{
|
{
|
||||||
|
friend class TWorld; // temporary due to use of play_sound TODO: refactor this
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool CabChange(int iDirection);
|
bool CabChange(int iDirection);
|
||||||
bool ShowNextCurrent; // pokaz przd w podlaczonej lokomotywie (ET41)
|
bool ShowNextCurrent; // pokaz przd w podlaczonej lokomotywie (ET41)
|
||||||
@@ -468,6 +470,7 @@ public: // reszta może by?publiczna
|
|||||||
int iUnits[20]; // numer jednostki
|
int iUnits[20]; // numer jednostki
|
||||||
int iDoorNo[20]; // liczba drzwi
|
int iDoorNo[20]; // liczba drzwi
|
||||||
char cCode[20]; // kod pojazdu
|
char cCode[20]; // kod pojazdu
|
||||||
|
bool bSlip[20]; // poślizg kół pojazdu
|
||||||
std::string asCarName[20]; // nazwa czlonu
|
std::string asCarName[20]; // nazwa czlonu
|
||||||
bool bMains[8]; // WSy
|
bool bMains[8]; // WSy
|
||||||
float fCntVol[8]; // napiecie NN
|
float fCntVol[8]; // napiecie NN
|
||||||
|
|||||||
25
TrkFoll.cpp
25
TrkFoll.cpp
@@ -15,11 +15,10 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "TrkFoll.h"
|
#include "TrkFoll.h"
|
||||||
|
|
||||||
|
#include "simulation.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "Driver.h"
|
|
||||||
#include "DynObj.h"
|
|
||||||
#include "Event.h"
|
|
||||||
|
|
||||||
TTrackFollower::~TTrackFollower()
|
TTrackFollower::~TTrackFollower()
|
||||||
{
|
{
|
||||||
@@ -116,7 +115,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
&& ( pCurrentTrack->evEvent1 )
|
&& ( pCurrentTrack->evEvent1 )
|
||||||
&& ( !pCurrentTrack->evEvent1->iQueued ) ) {
|
&& ( !pCurrentTrack->evEvent1->iQueued ) ) {
|
||||||
// dodanie do kolejki
|
// dodanie do kolejki
|
||||||
Global::AddToQuery( pCurrentTrack->evEvent1, Owner );
|
simulation::Events.AddToQuery( pCurrentTrack->evEvent1, Owner );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +126,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
-1)) // McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow
|
-1)) // McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow
|
||||||
if (bPrimary && pCurrentTrack->evEventall1 &&
|
if (bPrimary && pCurrentTrack->evEventall1 &&
|
||||||
(!pCurrentTrack->evEventall1->iQueued))
|
(!pCurrentTrack->evEventall1->iQueued))
|
||||||
Global::AddToQuery(pCurrentTrack->evEventall1, Owner); // dodanie do kolejki
|
simulation::Events.AddToQuery(pCurrentTrack->evEventall1, Owner); // dodanie do kolejki
|
||||||
// Owner->RaAxleEvent(pCurrentTrack->Eventall1); //Ra: dynamic zdecyduje, czy dodać
|
// Owner->RaAxleEvent(pCurrentTrack->Eventall1); //Ra: dynamic zdecyduje, czy dodać
|
||||||
// do kolejki
|
// do kolejki
|
||||||
}
|
}
|
||||||
@@ -142,7 +141,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
if( ( bPrimary )
|
if( ( bPrimary )
|
||||||
&& ( pCurrentTrack->evEvent2 )
|
&& ( pCurrentTrack->evEvent2 )
|
||||||
&& ( !pCurrentTrack->evEvent2->iQueued ) ) {
|
&& ( !pCurrentTrack->evEvent2->iQueued ) ) {
|
||||||
Global::AddToQuery( pCurrentTrack->evEvent2, Owner );
|
simulation::Events.AddToQuery( pCurrentTrack->evEvent2, Owner );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +153,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
if( ( bPrimary )
|
if( ( bPrimary )
|
||||||
&& ( pCurrentTrack->evEventall2 )
|
&& ( pCurrentTrack->evEventall2 )
|
||||||
&& ( !pCurrentTrack->evEventall2->iQueued ) ) {
|
&& ( !pCurrentTrack->evEventall2->iQueued ) ) {
|
||||||
Global::AddToQuery( pCurrentTrack->evEventall2, Owner );
|
simulation::Events.AddToQuery( pCurrentTrack->evEventall2, Owner );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Owner->RaAxleEvent(pCurrentTrack->Eventall2); //Ra: dynamic zdecyduje, czy dodać
|
// Owner->RaAxleEvent(pCurrentTrack->Eventall2); //Ra: dynamic zdecyduje, czy dodać
|
||||||
@@ -167,13 +166,13 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
// tylko dla jednego członu
|
// tylko dla jednego członu
|
||||||
if( pCurrentTrack->evEvent0 )
|
if( pCurrentTrack->evEvent0 )
|
||||||
if( !pCurrentTrack->evEvent0->iQueued )
|
if( !pCurrentTrack->evEvent0->iQueued )
|
||||||
Global::AddToQuery( pCurrentTrack->evEvent0, Owner );
|
simulation::Events.AddToQuery( pCurrentTrack->evEvent0, Owner );
|
||||||
}
|
}
|
||||||
// Owner->RaAxleEvent(pCurrentTrack->Event0); //Ra: dynamic zdecyduje, czy dodać do
|
// Owner->RaAxleEvent(pCurrentTrack->Event0); //Ra: dynamic zdecyduje, czy dodać do
|
||||||
// kolejki
|
// kolejki
|
||||||
if (pCurrentTrack->evEventall0)
|
if (pCurrentTrack->evEventall0)
|
||||||
if (!pCurrentTrack->evEventall0->iQueued)
|
if (!pCurrentTrack->evEventall0->iQueued)
|
||||||
Global::AddToQuery(pCurrentTrack->evEventall0, Owner);
|
simulation::Events.AddToQuery(pCurrentTrack->evEventall0, Owner);
|
||||||
// Owner->RaAxleEvent(pCurrentTrack->Eventall0); //Ra: dynamic zdecyduje, czy dodać
|
// Owner->RaAxleEvent(pCurrentTrack->Eventall0); //Ra: dynamic zdecyduje, czy dodać
|
||||||
// do kolejki
|
// do kolejki
|
||||||
}
|
}
|
||||||
@@ -275,14 +274,14 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
// if (Owner->MoverParameters->CabNo!=0)
|
// if (Owner->MoverParameters->CabNo!=0)
|
||||||
{
|
{
|
||||||
if (pCurrentTrack->evEvent1 && pCurrentTrack->evEvent1->fDelay <= -1.0f)
|
if (pCurrentTrack->evEvent1 && pCurrentTrack->evEvent1->fDelay <= -1.0f)
|
||||||
Global::AddToQuery(pCurrentTrack->evEvent1, Owner);
|
simulation::Events.AddToQuery(pCurrentTrack->evEvent1, Owner);
|
||||||
if (pCurrentTrack->evEvent2 && pCurrentTrack->evEvent2->fDelay <= -1.0f)
|
if (pCurrentTrack->evEvent2 && pCurrentTrack->evEvent2->fDelay <= -1.0f)
|
||||||
Global::AddToQuery(pCurrentTrack->evEvent2, Owner);
|
simulation::Events.AddToQuery(pCurrentTrack->evEvent2, Owner);
|
||||||
}
|
}
|
||||||
if (pCurrentTrack->evEventall1 && pCurrentTrack->evEventall1->fDelay <= -1.0f)
|
if (pCurrentTrack->evEventall1 && pCurrentTrack->evEventall1->fDelay <= -1.0f)
|
||||||
Global::AddToQuery(pCurrentTrack->evEventall1, Owner);
|
simulation::Events.AddToQuery(pCurrentTrack->evEventall1, Owner);
|
||||||
if (pCurrentTrack->evEventall2 && pCurrentTrack->evEventall2->fDelay <= -1.0f)
|
if (pCurrentTrack->evEventall2 && pCurrentTrack->evEventall2->fDelay <= -1.0f)
|
||||||
Global::AddToQuery(pCurrentTrack->evEventall2, Owner);
|
simulation::Events.AddToQuery(pCurrentTrack->evEventall2, Owner);
|
||||||
}
|
}
|
||||||
fCurrentDistance = s;
|
fCurrentDistance = s;
|
||||||
// fDistance=0;
|
// fDistance=0;
|
||||||
|
|||||||
11
World.h
11
World.h
@@ -11,14 +11,16 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Ground.h"
|
#include "scene.h"
|
||||||
#include "sky.h"
|
#include "sky.h"
|
||||||
#include "sun.h"
|
#include "sun.h"
|
||||||
#include "moon.h"
|
#include "moon.h"
|
||||||
#include "stars.h"
|
#include "stars.h"
|
||||||
#include "skydome.h"
|
#include "skydome.h"
|
||||||
#include "McZapkie/MOVER.h"
|
#include "McZapkie/MOVER.h"
|
||||||
|
#include "messaging.h"
|
||||||
|
|
||||||
// wrapper for simulation time
|
// wrapper for simulation time
|
||||||
class simulation_time {
|
class simulation_time {
|
||||||
@@ -105,12 +107,15 @@ TWorld();
|
|||||||
void OnKeyDown(int cKey);
|
void OnKeyDown(int cKey);
|
||||||
// void UpdateWindow();
|
// void UpdateWindow();
|
||||||
void OnMouseMove(double x, double y);
|
void OnMouseMove(double x, double y);
|
||||||
void OnCommandGet(DaneRozkaz *pRozkaz);
|
void OnCommandGet(multiplayer::DaneRozkaz *pRozkaz);
|
||||||
bool Update();
|
bool Update();
|
||||||
void TrainDelete(TDynamicObject *d = NULL);
|
void TrainDelete(TDynamicObject *d = NULL);
|
||||||
TTrain* train() { return Train; }
|
TTrain* train() { return Train; }
|
||||||
// switches between static and dynamic daylight calculation
|
// switches between static and dynamic daylight calculation
|
||||||
void ToggleDaylight();
|
void ToggleDaylight();
|
||||||
|
// calculates current season of the year based on set simulation date
|
||||||
|
void compute_season( int const Yearday ) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Update_Environment();
|
void Update_Environment();
|
||||||
@@ -144,8 +149,6 @@ private:
|
|||||||
void CabChange(TDynamicObject *old, TDynamicObject *now);
|
void CabChange(TDynamicObject *old, TDynamicObject *now);
|
||||||
// handles vehicle change flag
|
// handles vehicle change flag
|
||||||
void ChangeDynamic();
|
void ChangeDynamic();
|
||||||
|
|
||||||
TGround Ground; //m7todo: tmp
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ public:
|
|||||||
point_inside( float const X, float const Y, float const Z ) const;
|
point_inside( float const X, float const Y, float const Z ) const;
|
||||||
// tests if the sphere is in frustum, returns the distance between origin and sphere centre
|
// tests if the sphere is in frustum, returns the distance between origin and sphere centre
|
||||||
inline
|
inline
|
||||||
|
float
|
||||||
|
sphere_inside( glm::dvec3 const &Center, float const Radius ) const { return sphere_inside( static_cast<float>( Center.x ), static_cast<float>( Center.y ), static_cast<float>( Center.z ), Radius ); }
|
||||||
|
inline
|
||||||
float
|
float
|
||||||
sphere_inside( glm::vec3 const &Center, float const Radius ) const { return sphere_inside( Center.x, Center.y, Center.z, Radius ); }
|
sphere_inside( glm::vec3 const &Center, float const Radius ) const { return sphere_inside( Center.x, Center.y, Center.z, Radius ); }
|
||||||
inline
|
inline
|
||||||
|
|||||||
29
lua.cpp
29
lua.cpp
@@ -6,6 +6,7 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "Driver.h"
|
#include "Driver.h"
|
||||||
#include "lua_ffi.h"
|
#include "lua_ffi.h"
|
||||||
|
#include "simulation.h"
|
||||||
|
|
||||||
extern TWorld World;
|
extern TWorld World;
|
||||||
|
|
||||||
@@ -72,29 +73,31 @@ extern "C"
|
|||||||
event->asName = std::string(name);
|
event->asName = std::string(name);
|
||||||
event->fDelay = delay;
|
event->fDelay = delay;
|
||||||
event->Params[0].asPointer = (void*)handler;
|
event->Params[0].asPointer = (void*)handler;
|
||||||
World.Ground.add_event(event);
|
if (simulation::Events.insert(event))
|
||||||
return event;
|
return event;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT TEvent* scriptapi_event_find(const char* name)
|
EXPORT TEvent* scriptapi_event_find(const char* name)
|
||||||
{
|
{
|
||||||
std::string str(name);
|
std::string str(name);
|
||||||
TEvent *e = World.Ground.FindEvent(str);
|
TEvent *e = simulation::Events.FindEvent(str);
|
||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
else
|
else
|
||||||
WriteLog("missing event: " + str);
|
WriteLog("lua: missing event: " + str);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT TTrack* scriptapi_track_find(const char* name)
|
EXPORT TTrack* scriptapi_track_find(const char* name)
|
||||||
{
|
{
|
||||||
std::string str(name);
|
std::string str(name);
|
||||||
TGroundNode *n = World.Ground.FindGroundNode(str, TP_TRACK);
|
TTrack *track = simulation::Paths.find(str);
|
||||||
if (n)
|
if (track)
|
||||||
return n->pTrack;
|
return track;
|
||||||
else
|
else
|
||||||
WriteLog("missing track: " + str);
|
WriteLog("lua: missing track: " + str);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +125,7 @@ extern "C"
|
|||||||
EXPORT void scriptapi_event_dispatch(TEvent *e, TDynamicObject *activator)
|
EXPORT void scriptapi_event_dispatch(TEvent *e, TDynamicObject *activator)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
World.Ground.AddToQuery(e, activator);
|
simulation::Events.AddToQuery(e, activator);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT double scriptapi_random(double a, double b)
|
EXPORT double scriptapi_random(double a, double b)
|
||||||
@@ -132,7 +135,7 @@ extern "C"
|
|||||||
|
|
||||||
EXPORT void scriptapi_writelog(const char* txt)
|
EXPORT void scriptapi_writelog(const char* txt)
|
||||||
{
|
{
|
||||||
WriteLog("lua log: " + std::string(txt));
|
WriteLog("lua: log: " + std::string(txt));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct memcell_values { const char *str; double num1; double num2; };
|
struct memcell_values { const char *str; double num1; double num2; };
|
||||||
@@ -140,11 +143,11 @@ extern "C"
|
|||||||
EXPORT TMemCell* scriptapi_memcell_find(const char *name)
|
EXPORT TMemCell* scriptapi_memcell_find(const char *name)
|
||||||
{
|
{
|
||||||
std::string str(name);
|
std::string str(name);
|
||||||
TGroundNode *n = World.Ground.FindGroundNode(str, TP_MEMCELL);
|
TMemCell *mc = simulation::Memory.find(str);
|
||||||
if (n)
|
if (mc)
|
||||||
return n->MemCell;
|
return mc;
|
||||||
else
|
else
|
||||||
WriteLog("missing memcell: " + str);
|
WriteLog("lua: missing memcell: " + str);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
material.cpp
33
material.cpp
@@ -18,7 +18,7 @@ bool
|
|||||||
opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
|
opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
|
||||||
|
|
||||||
bool result { false };
|
bool result { false };
|
||||||
while( true == deserialize_mapping( Input, Loadnow ) ) {
|
while( true == deserialize_mapping( Input, 0, Loadnow ) ) {
|
||||||
result = true; // once would suffice but, eh
|
result = true; // once would suffice but, eh
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
|
|||||||
|
|
||||||
// imports member data pair from the config file
|
// imports member data pair from the config file
|
||||||
bool
|
bool
|
||||||
opengl_material::deserialize_mapping( cParser &Input, bool const Loadnow ) {
|
opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow ) {
|
||||||
|
|
||||||
if( false == Input.getTokens( 2, true, "\n\r\t;, " ) ) {
|
if( false == Input.getTokens( 2, true, "\n\r\t;, " ) ) {
|
||||||
return false;
|
return false;
|
||||||
@@ -48,8 +48,30 @@ opengl_material::deserialize_mapping( cParser &Input, bool const Loadnow ) {
|
|||||||
>> key
|
>> key
|
||||||
>> value;
|
>> value;
|
||||||
|
|
||||||
if( key == "texture1:" ) { texture1 = GfxRenderer.Fetch_Texture( path + value, Loadnow ); }
|
if( value == "{" ) {
|
||||||
else if( key == "texture2:" ) { texture2 = GfxRenderer.Fetch_Texture( path + value, Loadnow ); }
|
// detect and optionally process config blocks
|
||||||
|
cParser blockparser( Input.getToken<std::string>( false, "}" ) );
|
||||||
|
if( key == Global::Season ) {
|
||||||
|
// seasonal textures override generic textures
|
||||||
|
while( true == deserialize_mapping( blockparser, 1, Loadnow ) ) {
|
||||||
|
; // all work is done in the header
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( key == "texture1:" ) {
|
||||||
|
// TODO: full-fledged priority system
|
||||||
|
if( ( texture1 == null_handle )
|
||||||
|
|| ( Priority > 0 ) ) {
|
||||||
|
texture1 = GfxRenderer.Fetch_Texture( path + value, Loadnow );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( key == "texture2:" ) {
|
||||||
|
// TODO: full-fledged priority system
|
||||||
|
if( ( texture2 == null_handle )
|
||||||
|
|| ( Priority > 0 ) ) {
|
||||||
|
texture2 = GfxRenderer.Fetch_Texture( path + value, Loadnow );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
|
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
|
||||||
}
|
}
|
||||||
@@ -65,7 +87,8 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
|||||||
if( filename.find( '|' ) != std::string::npos )
|
if( filename.find( '|' ) != std::string::npos )
|
||||||
filename.erase( filename.find( '|' ) ); // po | może być nazwa kolejnej tekstury
|
filename.erase( filename.find( '|' ) ); // po | może być nazwa kolejnej tekstury
|
||||||
|
|
||||||
if( filename.rfind( '.' ) != std::string::npos ) {
|
if( ( filename.rfind( '.' ) != std::string::npos )
|
||||||
|
&& ( filename.rfind( '.' ) != filename.rfind( ".." ) + 1 ) ) {
|
||||||
// we can get extension for .mat or, in legacy files, some image format. just trim it and set it to material file extension
|
// we can get extension for .mat or, in legacy files, some image format. just trim it and set it to material file extension
|
||||||
filename.erase( filename.rfind( '.' ) );
|
filename.erase( filename.rfind( '.' ) );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ struct opengl_material {
|
|||||||
bool
|
bool
|
||||||
deserialize( cParser &Input, bool const Loadnow );
|
deserialize( cParser &Input, bool const Loadnow );
|
||||||
private:
|
private:
|
||||||
// imports member data pair from the config file
|
// imports member data pair from the config file, overriding existing parameter values of lower priority
|
||||||
bool
|
bool
|
||||||
deserialize_mapping( cParser &Input, bool const Loadnow );
|
deserialize_mapping( cParser &Input, int const Priority, bool const Loadnow );
|
||||||
};
|
};
|
||||||
|
|
||||||
class material_manager {
|
class material_manager {
|
||||||
|
|||||||
258
messaging.cpp
Normal file
258
messaging.cpp
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "messaging.h"
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "simulation.h"
|
||||||
|
#include "mtable.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
GLFWAPI HWND glfwGetWin32Window( GLFWwindow* window ); //m7todo: potrzebne do directsound
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace multiplayer {
|
||||||
|
|
||||||
|
void
|
||||||
|
Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// wysłanie komunikatu do sterującego
|
||||||
|
HWND h = FindWindow(ClassName.c_str(), 0); // można by to zapamiętać
|
||||||
|
if (h == 0)
|
||||||
|
h = FindWindow(0, ClassName.c_str()); // można by to zapamiętać
|
||||||
|
SendMessage(h, Msg, wParam, lParam);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijEvent(const std::string &e, const std::string &d)
|
||||||
|
{ // Ra: jeszcze do wyczyszczenia
|
||||||
|
#ifdef _WIN32
|
||||||
|
DaneRozkaz r;
|
||||||
|
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
|
||||||
|
r.iComm = 2; // 2 - event
|
||||||
|
size_t i = e.length(), j = d.length();
|
||||||
|
r.cString[0] = char(i);
|
||||||
|
strcpy(r.cString + 1, e.c_str()); // zakończony zerem
|
||||||
|
r.cString[i + 2] = char(j); // licznik po zerze kończącym
|
||||||
|
strcpy(r.cString + 3 + i, d.c_str()); // zakończony zerem
|
||||||
|
COPYDATASTRUCT cData;
|
||||||
|
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||||
|
cData.cbData = (DWORD)(12 + i + j); // 8+dwa liczniki i dwa zera kończące
|
||||||
|
cData.lpData = &r;
|
||||||
|
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
|
||||||
|
CommLog( Now() + " " + std::to_string(r.iComm) + " " + e + " sent" );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijUszkodzenia(const std::string &t, char fl)
|
||||||
|
{ // wysłanie informacji w postaci pojedynczego tekstu
|
||||||
|
#ifdef _WIN32
|
||||||
|
DaneRozkaz r;
|
||||||
|
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
|
||||||
|
r.iComm = 13; // numer komunikatu
|
||||||
|
size_t i = t.length();
|
||||||
|
r.cString[0] = char(fl);
|
||||||
|
r.cString[1] = char(i);
|
||||||
|
strcpy(r.cString + 2, t.c_str()); // z zerem kończącym
|
||||||
|
COPYDATASTRUCT cData;
|
||||||
|
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||||
|
cData.cbData = (DWORD)(11 + i); // 8+licznik i zero kończące
|
||||||
|
cData.lpData = &r;
|
||||||
|
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
|
||||||
|
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijString(const std::string &t, int n)
|
||||||
|
{ // wysłanie informacji w postaci pojedynczego tekstu
|
||||||
|
#ifdef _WIN32
|
||||||
|
DaneRozkaz r;
|
||||||
|
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
|
||||||
|
r.iComm = n; // numer komunikatu
|
||||||
|
size_t i = t.length();
|
||||||
|
r.cString[0] = char(i);
|
||||||
|
strcpy(r.cString + 1, t.c_str()); // z zerem kończącym
|
||||||
|
COPYDATASTRUCT cData;
|
||||||
|
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||||
|
cData.cbData = (DWORD)(10 + i); // 8+licznik i zero kończące
|
||||||
|
cData.lpData = &r;
|
||||||
|
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
|
||||||
|
CommLog( Now() + " " + std::to_string(r.iComm) + " " + t + " sent");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijWolny(const std::string &t)
|
||||||
|
{ // Ra: jeszcze do wyczyszczenia
|
||||||
|
WyslijString(t, 4); // tor wolny
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijNamiary(TDynamicObject const *Vehicle)
|
||||||
|
{ // wysłanie informacji o pojeździe - (float), długość ramki będzie zwiększana w miarę potrzeby
|
||||||
|
#ifdef _WIN32
|
||||||
|
// WriteLog("Wysylam pojazd");
|
||||||
|
DaneRozkaz r;
|
||||||
|
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
|
||||||
|
r.iComm = 7; // 7 - dane pojazdu
|
||||||
|
int i = 32;
|
||||||
|
size_t j = Vehicle->asName.length();
|
||||||
|
r.iPar[0] = i; // ilość danych liczbowych
|
||||||
|
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
|
||||||
|
r.fPar[2] = Vehicle->MoverParameters->Loc.X; // pozycja X
|
||||||
|
r.fPar[3] = Vehicle->MoverParameters->Loc.Y; // pozycja Y
|
||||||
|
r.fPar[4] = Vehicle->MoverParameters->Loc.Z; // pozycja Z
|
||||||
|
r.fPar[5] = Vehicle->MoverParameters->V; // prędkość ruchu X
|
||||||
|
r.fPar[6] = Vehicle->MoverParameters->nrot * M_PI *
|
||||||
|
Vehicle->MoverParameters->WheelDiameter; // prędkość obrotowa kóŁ
|
||||||
|
r.fPar[7] = 0; // prędkość ruchu Z
|
||||||
|
r.fPar[8] = Vehicle->MoverParameters->AccS; // przyspieszenie X
|
||||||
|
r.fPar[9] = Vehicle->MoverParameters->AccN; // przyspieszenie Y //na razie nie
|
||||||
|
r.fPar[10] = Vehicle->MoverParameters->AccV; // przyspieszenie Z
|
||||||
|
r.fPar[11] = Vehicle->MoverParameters->DistCounter; // przejechana odległość w km
|
||||||
|
r.fPar[12] = Vehicle->MoverParameters->PipePress; // ciśnienie w PG
|
||||||
|
r.fPar[13] = Vehicle->MoverParameters->ScndPipePress; // ciśnienie w PZ
|
||||||
|
r.fPar[14] = Vehicle->MoverParameters->BrakePress; // ciśnienie w CH
|
||||||
|
r.fPar[15] = Vehicle->MoverParameters->Compressor; // ciśnienie w ZG
|
||||||
|
r.fPar[16] = Vehicle->MoverParameters->Itot; // Prąd całkowity
|
||||||
|
r.iPar[17] = Vehicle->MoverParameters->MainCtrlPos; // Pozycja NJ
|
||||||
|
r.iPar[18] = Vehicle->MoverParameters->ScndCtrlPos; // Pozycja NB
|
||||||
|
r.iPar[19] = Vehicle->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
|
||||||
|
r.iPar[20] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
|
||||||
|
r.iPar[21] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
|
||||||
|
r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1 +
|
||||||
|
Vehicle->MoverParameters->ConverterFlag * 2 +
|
||||||
|
+Vehicle->MoverParameters->CompressorFlag * 4 +
|
||||||
|
Vehicle->MoverParameters->Mains * 8 +
|
||||||
|
+Vehicle->MoverParameters->DoorLeftOpened * 16 +
|
||||||
|
Vehicle->MoverParameters->DoorRightOpened * 32 +
|
||||||
|
+Vehicle->MoverParameters->FuseFlag * 64 +
|
||||||
|
Vehicle->MoverParameters->DepartureSignal * 128;
|
||||||
|
// WriteLog("Zapisalem stare");
|
||||||
|
// WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
|
||||||
|
for (int p = 0; p < 4; p++)
|
||||||
|
{
|
||||||
|
// WriteLog("Probuje pant "+IntToStr(p));
|
||||||
|
if (p < Vehicle->iAnimType[ANIM_PANTS])
|
||||||
|
{
|
||||||
|
r.fPar[23 + p] = Vehicle->pants[p].fParamPants->PantWys; // stan pantografów 4
|
||||||
|
// WriteLog("Zapisalem pant "+IntToStr(p));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r.fPar[23 + p] = -2;
|
||||||
|
// WriteLog("Nie mam pant "+IntToStr(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// WriteLog("Zapisalem pantografy");
|
||||||
|
for (int p = 0; p < 3; p++)
|
||||||
|
r.fPar[27 + p] =
|
||||||
|
Vehicle->MoverParameters->ShowCurrent(p + 1); // amperomierze kolejnych grup
|
||||||
|
// WriteLog("zapisalem prady");
|
||||||
|
r.iPar[30] = Vehicle->MoverParameters->WarningSignal; // trabienie
|
||||||
|
r.fPar[31] = Vehicle->MoverParameters->RunningTraction.TractionVoltage; // napiecie WN
|
||||||
|
// WriteLog("Parametry gotowe");
|
||||||
|
i <<= 2; // ilość bajtów
|
||||||
|
r.cString[i] = char(j); // na końcu nazwa, żeby jakoś zidentyfikować
|
||||||
|
strcpy(r.cString + i + 1, Vehicle->asName.c_str()); // zakończony zerem
|
||||||
|
COPYDATASTRUCT cData;
|
||||||
|
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||||
|
cData.cbData = (DWORD)(10 + i + j); // 8+licznik i zero kończące
|
||||||
|
cData.lpData = &r;
|
||||||
|
// WriteLog("Ramka gotowa");
|
||||||
|
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
|
||||||
|
// WriteLog("Ramka poszla!");
|
||||||
|
CommLog( Now() + " " + std::to_string(r.iComm) + " " + Vehicle->asName + " sent");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijObsadzone()
|
||||||
|
{ // wysłanie informacji o pojeździe
|
||||||
|
#ifdef _WIN32
|
||||||
|
DaneRozkaz2 r;
|
||||||
|
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
|
||||||
|
r.iComm = 12; // kod 12
|
||||||
|
for (int i=0; i<1984; ++i) r.cString[i] = 0;
|
||||||
|
|
||||||
|
// TODO: clean this up, we shouldn't be relying on direct list access
|
||||||
|
auto &vehiclelist = simulation::Vehicles.sequence();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for( auto *vehicle : vehiclelist ) {
|
||||||
|
if( vehicle->Mechanik ) {
|
||||||
|
strcpy( r.cString + 64 * i, vehicle->asName.c_str() );
|
||||||
|
r.fPar[ 16 * i + 4 ] = vehicle->GetPosition().x;
|
||||||
|
r.fPar[ 16 * i + 5 ] = vehicle->GetPosition().y;
|
||||||
|
r.fPar[ 16 * i + 6 ] = vehicle->GetPosition().z;
|
||||||
|
r.iPar[ 16 * i + 7 ] = vehicle->Mechanik->GetAction();
|
||||||
|
strcpy( r.cString + 64 * i + 32, vehicle->GetTrack()->IsolatedName().c_str() );
|
||||||
|
strcpy( r.cString + 64 * i + 48, vehicle->Mechanik->Timetable()->TrainName.c_str() );
|
||||||
|
i++;
|
||||||
|
if( i > 30 ) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (i <= 30)
|
||||||
|
{
|
||||||
|
strcpy(r.cString + 64 * i, "none");
|
||||||
|
r.fPar[16 * i + 4] = 1;
|
||||||
|
r.fPar[16 * i + 5] = 2;
|
||||||
|
r.fPar[16 * i + 6] = 3;
|
||||||
|
r.iPar[16 * i + 7] = 0;
|
||||||
|
strcpy(r.cString + 64 * i + 32, "none");
|
||||||
|
strcpy(r.cString + 64 * i + 48, "none");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
COPYDATASTRUCT cData;
|
||||||
|
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||||
|
cData.cbData = 8 + 1984; // 8+licznik i zero kończące
|
||||||
|
cData.lpData = &r;
|
||||||
|
// WriteLog("Ramka gotowa");
|
||||||
|
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
|
||||||
|
CommLog( Now() + " " + std::to_string(r.iComm) + " obsadzone" + " sent");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WyslijParam(int nr, int fl)
|
||||||
|
{ // wysłanie parametrów symulacji w ramce (nr) z flagami (fl)
|
||||||
|
#ifdef _WIN32
|
||||||
|
DaneRozkaz r;
|
||||||
|
r.iSygn = MAKE_ID4( 'E', 'U', '0', '7' );
|
||||||
|
r.iComm = nr; // zwykle 5
|
||||||
|
r.iPar[0] = fl; // flagi istotności kolejnych parametrów
|
||||||
|
int i = 0; // domyślnie brak danych
|
||||||
|
switch (nr)
|
||||||
|
{ // można tym przesyłać różne zestawy parametrów
|
||||||
|
case 5: // czas i pauza
|
||||||
|
r.fPar[1] = Global::fTimeAngleDeg / 360.0; // aktualny czas (1.0=doba)
|
||||||
|
r.iPar[2] = Global::iPause; // stan zapauzowania
|
||||||
|
i = 8; // dwa parametry po 4 bajty każdy
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
COPYDATASTRUCT cData;
|
||||||
|
cData.dwData = MAKE_ID4( 'E', 'U', '0', '7' ); // sygnatura
|
||||||
|
cData.cbData = 12 + i; // 12+rozmiar danych
|
||||||
|
cData.lpData = &r;
|
||||||
|
Navigate( "TEU07SRK", WM_COPYDATA, (WPARAM)glfwGetWin32Window( Global::window ), (LPARAM)&cData );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // multiplayer
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
51
messaging.h
Normal file
51
messaging.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "winheaders.h"
|
||||||
|
|
||||||
|
class TDynamicObject;
|
||||||
|
|
||||||
|
namespace multiplayer {
|
||||||
|
|
||||||
|
struct DaneRozkaz { // struktura komunikacji z EU07.EXE
|
||||||
|
int iSygn; // sygnatura 'EU07'
|
||||||
|
int iComm; // rozkaz/status (kod ramki)
|
||||||
|
union {
|
||||||
|
float fPar[ 62 ];
|
||||||
|
int iPar[ 62 ];
|
||||||
|
char cString[ 248 ]; // upakowane stringi
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DaneRozkaz2 { // struktura komunikacji z EU07.EXE
|
||||||
|
int iSygn; // sygnatura 'EU07'
|
||||||
|
int iComm; // rozkaz/status (kod ramki)
|
||||||
|
union {
|
||||||
|
float fPar[ 496 ];
|
||||||
|
int iPar[ 496 ];
|
||||||
|
char cString[ 1984 ]; // upakowane stringi
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void Navigate( std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam );
|
||||||
|
|
||||||
|
void WyslijEvent( const std::string &e, const std::string &d );
|
||||||
|
void WyslijString( const std::string &t, int n );
|
||||||
|
void WyslijWolny( const std::string &t );
|
||||||
|
void WyslijNamiary( TDynamicObject const *Vehicle );
|
||||||
|
void WyslijParam( int nr, int fl );
|
||||||
|
void WyslijUszkodzenia( const std::string &t, char fl );
|
||||||
|
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
||||||
|
|
||||||
|
} // multiplayer
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
@@ -363,6 +363,12 @@ mouse_input::default_bindings() {
|
|||||||
{ "pantselectedoff_sw:", {
|
{ "pantselectedoff_sw:", {
|
||||||
user_command::none,
|
user_command::none,
|
||||||
user_command::none } }, // TODO: lower selected pantograp(s) command
|
user_command::none } }, // TODO: lower selected pantograp(s) command
|
||||||
|
{ "pantcompressor_sw:", {
|
||||||
|
user_command::pantographcompressoractivate,
|
||||||
|
user_command::none } },
|
||||||
|
{ "pantcompressorvalve_sw:", {
|
||||||
|
user_command::pantographcompressorvalvetoggle,
|
||||||
|
user_command::none } },
|
||||||
{ "trainheating_sw:", {
|
{ "trainheating_sw:", {
|
||||||
user_command::heatingtoggle,
|
user_command::heatingtoggle,
|
||||||
user_command::none } },
|
user_command::none } },
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct basic_vertex {
|
|||||||
glm::vec2 texture; // uv space
|
glm::vec2 texture; // uv space
|
||||||
|
|
||||||
basic_vertex() = default;
|
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 )
|
position( Position ), normal( Normal ), texture( Texture )
|
||||||
{}
|
{}
|
||||||
void serialize( std::ostream& ) const;
|
void serialize( std::ostream& ) const;
|
||||||
@@ -58,7 +58,7 @@ struct geometry_handle {
|
|||||||
geometry_handle() :
|
geometry_handle() :
|
||||||
bank( 0 ), chunk( 0 )
|
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 )
|
bank( Bank ), chunk( Chunk )
|
||||||
{}
|
{}
|
||||||
// methods
|
// methods
|
||||||
@@ -121,7 +121,7 @@ protected:
|
|||||||
unsigned int type; // kind of geometry used by the chunk
|
unsigned int type; // kind of geometry used by the chunk
|
||||||
vertex_array vertices; // geometry data
|
vertex_array vertices; // geometry data
|
||||||
// NOTE: constructor doesn't copy provided vertex data, but moves it
|
// 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 )
|
type( Type )
|
||||||
{
|
{
|
||||||
vertices.swap( Vertices );
|
vertices.swap( Vertices );
|
||||||
|
|||||||
104
parser.cpp
104
parser.cpp
@@ -21,13 +21,14 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
// cParser -- generic class for parsing text data.
|
// cParser -- generic class for parsing text data.
|
||||||
|
|
||||||
// constructors
|
// constructors
|
||||||
cParser::cParser( std::string const &Stream, buffertype const Type, std::string Path, bool const Loadtraction ) :
|
cParser::cParser( std::string const &Stream, buffertype const Type, std::string Path, bool const Loadtraction, std::vector<std::string> Parameters ) :
|
||||||
mPath(Path),
|
mPath(Path),
|
||||||
LoadTraction( Loadtraction ) {
|
LoadTraction( Loadtraction ) {
|
||||||
// build comments map
|
// build comments map
|
||||||
mComments.insert(commentmap::value_type("/*", "*/"));
|
mComments.insert(commentmap::value_type("/*", "*/"));
|
||||||
mComments.insert(commentmap::value_type("//", "\n"));
|
mComments.insert(commentmap::value_type("//", "\n"));
|
||||||
// mComments.insert(commentmap::value_type("--","\n")); //Ra: to chyba nie używane
|
// mComments.insert(commentmap::value_type("--","\n")); //Ra: to chyba nie używane
|
||||||
|
|
||||||
// store to calculate sub-sequent includes from relative path
|
// store to calculate sub-sequent includes from relative path
|
||||||
if( Type == buffertype::buffer_FILE ) {
|
if( Type == buffertype::buffer_FILE ) {
|
||||||
mFile = Stream;
|
mFile = Stream;
|
||||||
@@ -60,6 +61,10 @@ cParser::cParser( std::string const &Stream, buffertype const Type, std::string
|
|||||||
mLine = 1;
|
mLine = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// set parameter set if one was provided
|
||||||
|
if( false == Parameters.empty() ) {
|
||||||
|
parameters.swap( Parameters );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -146,47 +151,21 @@ bool cParser::getTokens(unsigned int Count, bool ToLower, const char *Break)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cParser::readToken(bool ToLower, const char *Break)
|
std::string cParser::readToken( bool ToLower, const char *Break ) {
|
||||||
{
|
|
||||||
std::string token = "";
|
std::string token;
|
||||||
size_t pos; // początek podmienianego ciągu
|
if( mIncludeParser ) {
|
||||||
// see if there's include parsing going on. clean up when it's done.
|
// see if there's include parsing going on. clean up when it's done.
|
||||||
if (mIncludeParser)
|
|
||||||
{
|
|
||||||
token = mIncludeParser->readToken( ToLower, Break );
|
token = mIncludeParser->readToken( ToLower, Break );
|
||||||
if (!token.empty())
|
if( true == token.empty() ) {
|
||||||
{
|
mIncludeParser = nullptr;
|
||||||
// check if the token is a parameter which should be replaced with stored true value
|
|
||||||
while((pos = token.find("(p")) != std::string::npos) //!=npos to znalezione
|
|
||||||
{
|
|
||||||
std::string parameter =
|
|
||||||
token.substr(pos + 2, token.find(")", pos) - pos + 2); // numer parametru
|
|
||||||
token.erase(pos, token.find(")", pos) - pos + 1); // najpierw usunięcie "(pN)"
|
|
||||||
size_t nr = atoi(parameter.c_str()) - 1;
|
|
||||||
if (nr < parameters.size())
|
|
||||||
{
|
|
||||||
token.insert(pos, parameters.at(nr)); // wklejenie wartości parametru
|
|
||||||
if (ToLower)
|
|
||||||
for (; pos < token.length(); ++pos)
|
|
||||||
token[pos] = tolower(token[pos]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
token.insert(pos, "none"); // zabezpieczenie przed brakiem parametru
|
|
||||||
}
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mIncludeParser = NULL;
|
|
||||||
parameters.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// get the token yourself if there's no child to delegate it to.
|
if( true == token.empty() ) {
|
||||||
|
// get the token yourself if the delegation attempt failed
|
||||||
char c { 0 };
|
char c { 0 };
|
||||||
do
|
do {
|
||||||
{
|
while( mStream->peek() != EOF && strchr( Break, c = mStream->get() ) == NULL ) {
|
||||||
while (mStream->peek() != EOF && strchr(Break, c = mStream->get()) == NULL)
|
|
||||||
{
|
|
||||||
if( ToLower )
|
if( ToLower )
|
||||||
c = tolower( c );
|
c = tolower( c );
|
||||||
token += c;
|
token += c;
|
||||||
@@ -200,36 +179,55 @@ std::string cParser::readToken(bool ToLower, const char *Break)
|
|||||||
++mLine;
|
++mLine;
|
||||||
}
|
}
|
||||||
} while( token == "" && mStream->peek() != EOF ); // double check to deal with trailing spaces
|
} while( token == "" && mStream->peek() != EOF ); // double check to deal with trailing spaces
|
||||||
|
}
|
||||||
|
|
||||||
|
if( false == parameters.empty() ) {
|
||||||
|
// if there's parameter list, check the token for potential parameters to replace
|
||||||
|
size_t pos; // początek podmienianego ciągu
|
||||||
|
while( ( pos = token.find( "(p" ) ) != std::string::npos ) {
|
||||||
|
// check if the token is a parameter which should be replaced with stored true value
|
||||||
|
auto const parameter{ token.substr( pos + 2, token.find( ")", pos ) - ( pos + 2 ) ) }; // numer parametru
|
||||||
|
token.erase( pos, token.find( ")", pos ) - pos + 1 ); // najpierw usunięcie "(pN)"
|
||||||
|
size_t nr = atoi( parameter.c_str() ) - 1;
|
||||||
|
if( nr < parameters.size() ) {
|
||||||
|
token.insert( pos, parameters.at( nr ) ); // wklejenie wartości parametru
|
||||||
|
if( ToLower )
|
||||||
|
for( ; pos < parameters.at( nr ).size(); ++pos )
|
||||||
|
token[ pos ] = tolower( token[ pos ] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
token.insert( pos, "none" ); // zabezpieczenie przed brakiem parametru
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( token == "include" ) {
|
||||||
// launch child parser if include directive found.
|
// launch child parser if include directive found.
|
||||||
// NOTE: parameter collecting uses default set of token separators.
|
// NOTE: parameter collecting uses default set of token separators.
|
||||||
if (token.compare("include") == 0)
|
|
||||||
{ // obsługa include
|
|
||||||
std::string includefile = readToken(ToLower); // nazwa pliku
|
std::string includefile = readToken(ToLower); // nazwa pliku
|
||||||
if (LoadTraction ? true : ((includefile.find("tr/") == std::string::npos) &&
|
if( ( true == LoadTraction )
|
||||||
(includefile.find("tra/") == std::string::npos)))
|
|| ( ( includefile.find( "tr/" ) == std::string::npos )
|
||||||
{
|
&& ( includefile.find( "tra/" ) == std::string::npos ) ) ) {
|
||||||
// std::string trtest2="niemaproblema"; //nazwa odporna na znalezienie "tr/"
|
// get parameter list for the child parser
|
||||||
// if (trtest=="x") //jeśli nie wczytywać drutów
|
std::vector<std::string> includeparameters;
|
||||||
// trtest2=includefile; //kopiowanie ścieżki do pliku
|
|
||||||
std::string parameter = readToken( false ); // w parametrach nie zmniejszamy
|
std::string parameter = readToken( false ); // w parametrach nie zmniejszamy
|
||||||
while( ( parameter.empty() == false )
|
while( ( parameter.empty() == false )
|
||||||
&& (parameter.compare("end") != 0) )
|
&& ( parameter != "end" ) ) {
|
||||||
{
|
includeparameters.emplace_back( parameter );
|
||||||
parameters.push_back(parameter);
|
|
||||||
parameter = readToken( false );
|
parameter = readToken( false );
|
||||||
}
|
}
|
||||||
// if (trtest2.find("tr/")!=0)
|
mIncludeParser = std::make_shared<cParser>( includefile, buffer_FILE, mPath, LoadTraction, includeparameters );
|
||||||
mIncludeParser = std::make_shared<cParser>(includefile, buffer_FILE, mPath, LoadTraction);
|
if( mIncludeParser->mSize <= 0 ) {
|
||||||
if (mIncludeParser->mSize <= 0)
|
ErrorLog( "Bad include: can't open file \"" + includefile + "\"" );
|
||||||
ErrorLog("Missed include: " + includefile);
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while( token.compare( "end" ) != 0 ) {
|
while( token != "end" ) {
|
||||||
token = readToken( true ); // minimize risk of case mismatch on comparison
|
token = readToken( true ); // minimize risk of case mismatch on comparison
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token = readToken(ToLower, Break);
|
token = readToken(ToLower, Break);
|
||||||
}
|
}
|
||||||
|
// all done
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
parser.h
2
parser.h
@@ -28,7 +28,7 @@ class cParser //: public std::stringstream
|
|||||||
buffer_TEXT
|
buffer_TEXT
|
||||||
};
|
};
|
||||||
// constructors:
|
// constructors:
|
||||||
cParser(std::string const &Stream, buffertype const Type = buffer_TEXT, std::string Path = "", bool const Loadtraction = true );
|
cParser(std::string const &Stream, buffertype const Type = buffer_TEXT, std::string Path = "", bool const Loadtraction = true, std::vector<std::string> Parameters = std::vector<std::string>() );
|
||||||
// destructor:
|
// destructor:
|
||||||
virtual ~cParser();
|
virtual ~cParser();
|
||||||
// methods:
|
// methods:
|
||||||
|
|||||||
1274
renderer.cpp
1274
renderer.cpp
File diff suppressed because it is too large
Load Diff
81
renderer.h
81
renderer.h
@@ -17,10 +17,12 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "frustum.h"
|
#include "frustum.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "MemCell.h"
|
#include "MemCell.h"
|
||||||
|
#include "scene.h"
|
||||||
|
|
||||||
#define EU07_USE_PICKING_FRAMEBUFFER
|
#define EU07_USE_PICKING_FRAMEBUFFER
|
||||||
//#define EU07_USE_DEBUG_SHADOWMAP
|
//#define EU07_USE_DEBUG_SHADOWMAP
|
||||||
//#define EU07_USE_DEBUG_CAMERA
|
//#define EU07_USE_DEBUG_CAMERA
|
||||||
|
//#define EU07_USE_DEBUG_CULLING
|
||||||
|
|
||||||
struct opengl_light {
|
struct opengl_light {
|
||||||
|
|
||||||
@@ -84,7 +86,7 @@ public:
|
|||||||
void
|
void
|
||||||
update_frustum( glm::mat4 const &Projection, glm::mat4 const &Modelview );
|
update_frustum( glm::mat4 const &Projection, glm::mat4 const &Modelview );
|
||||||
bool
|
bool
|
||||||
visible( bounding_area const &Area ) const;
|
visible( scene::bounding_area const &Area ) const;
|
||||||
bool
|
bool
|
||||||
visible( TDynamicObject const *Dynamic ) const;
|
visible( TDynamicObject const *Dynamic ) const;
|
||||||
inline
|
inline
|
||||||
@@ -190,18 +192,20 @@ public:
|
|||||||
// utility methods
|
// utility methods
|
||||||
TSubModel const *
|
TSubModel const *
|
||||||
Pick_Control() const { return m_pickcontrolitem; }
|
Pick_Control() const { return m_pickcontrolitem; }
|
||||||
TGroundNode const *
|
editor::basic_node const *
|
||||||
Pick_Node() const { return m_picksceneryitem; }
|
Pick_Node() const { return m_picksceneryitem; }
|
||||||
// maintenance jobs
|
// maintenance jobs
|
||||||
void
|
void
|
||||||
Update( double const Deltatime );
|
Update( double const Deltatime );
|
||||||
TSubModel const *
|
TSubModel const *
|
||||||
Update_Pick_Control();
|
Update_Pick_Control();
|
||||||
TGroundNode const *
|
editor::basic_node const *
|
||||||
Update_Pick_Node();
|
Update_Pick_Node();
|
||||||
// debug performance string
|
// debug performance string
|
||||||
std::string const &
|
std::string const &
|
||||||
Info() const;
|
info_times() const;
|
||||||
|
std::string const &
|
||||||
|
info_stats() const;
|
||||||
|
|
||||||
// members
|
// members
|
||||||
GLenum static const sunlight{ GL_LIGHT0 };
|
GLenum static const sunlight{ GL_LIGHT0 };
|
||||||
@@ -225,7 +229,20 @@ private:
|
|||||||
diffuse
|
diffuse
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::pair< double, TSubRect * > distancesubcell_pair;
|
struct debug_stats {
|
||||||
|
int dynamics { 0 };
|
||||||
|
int models { 0 };
|
||||||
|
int submodels { 0 };
|
||||||
|
int paths { 0 };
|
||||||
|
int traction { 0 };
|
||||||
|
int shapes { 0 };
|
||||||
|
int lines { 0 };
|
||||||
|
int drawcalls { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
using section_sequence = std::vector<scene::basic_section *>;
|
||||||
|
using distancecell_pair = std::pair<double, scene::basic_cell *>;
|
||||||
|
using cell_sequence = std::vector<distancecell_pair>;
|
||||||
|
|
||||||
struct renderpass_config {
|
struct renderpass_config {
|
||||||
|
|
||||||
@@ -266,14 +283,16 @@ private:
|
|||||||
Render_reflections();
|
Render_reflections();
|
||||||
bool
|
bool
|
||||||
Render( world_environment *Environment );
|
Render( world_environment *Environment );
|
||||||
bool
|
void
|
||||||
Render( TGround *Ground );
|
Render( scene::basic_region *Region );
|
||||||
bool
|
void
|
||||||
Render( TGroundRect *Groundcell );
|
Render( section_sequence::iterator First, section_sequence::iterator Last );
|
||||||
bool
|
void
|
||||||
Render( TSubRect *Groundsubcell );
|
Render( cell_sequence::iterator First, cell_sequence::iterator Last );
|
||||||
bool
|
void
|
||||||
Render( TGroundNode *Node );
|
Render( scene::shape_node const &Shape, bool const Ignorerange );
|
||||||
|
void
|
||||||
|
Render( TAnimModel *Instance );
|
||||||
bool
|
bool
|
||||||
Render( TDynamicObject *Dynamic );
|
Render( TDynamicObject *Dynamic );
|
||||||
bool
|
bool
|
||||||
@@ -284,16 +303,22 @@ private:
|
|||||||
Render( TSubModel *Submodel );
|
Render( TSubModel *Submodel );
|
||||||
void
|
void
|
||||||
Render( TTrack *Track );
|
Render( TTrack *Track );
|
||||||
|
void
|
||||||
|
Render( scene::basic_cell::path_sequence::const_iterator First, scene::basic_cell::path_sequence::const_iterator Last );
|
||||||
bool
|
bool
|
||||||
Render_cab( TDynamicObject *Dynamic, bool const Alpha = false );
|
Render_cab( TDynamicObject *Dynamic, bool const Alpha = false );
|
||||||
void
|
void
|
||||||
Render( TMemCell *Memcell );
|
Render( TMemCell *Memcell );
|
||||||
bool
|
void
|
||||||
Render_Alpha( TGround *Ground );
|
Render_Alpha( scene::basic_region *Region );
|
||||||
bool
|
void
|
||||||
Render_Alpha( TSubRect *Groundsubcell );
|
Render_Alpha( cell_sequence::reverse_iterator First, cell_sequence::reverse_iterator Last );
|
||||||
bool
|
void
|
||||||
Render_Alpha( TGroundNode *Node );
|
Render_Alpha( TAnimModel *Instance );
|
||||||
|
void
|
||||||
|
Render_Alpha( TTraction *Traction );
|
||||||
|
void
|
||||||
|
Render_Alpha( scene::lines_node const &Lines );
|
||||||
bool
|
bool
|
||||||
Render_Alpha( TDynamicObject *Dynamic );
|
Render_Alpha( TDynamicObject *Dynamic );
|
||||||
bool
|
bool
|
||||||
@@ -351,28 +376,26 @@ private:
|
|||||||
units_state m_unitstate;
|
units_state m_unitstate;
|
||||||
|
|
||||||
unsigned int m_framestamp; // id of currently rendered gfx frame
|
unsigned int m_framestamp; // id of currently rendered gfx frame
|
||||||
float m_drawtime { 1000.f / 30.f * 20.f }; // start with presumed 'neutral' average of 30 fps
|
|
||||||
std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame
|
|
||||||
float m_framerate;
|
float m_framerate;
|
||||||
float m_drawtimecolorpass { 1000.f / 30.f * 20.f };
|
|
||||||
float m_drawtimeshadowpass { 0.f };
|
|
||||||
double m_updateaccumulator { 0.0 };
|
double m_updateaccumulator { 0.0 };
|
||||||
std::string m_debuginfo;
|
std::string m_debugtimestext;
|
||||||
std::string m_pickdebuginfo;
|
std::string m_pickdebuginfo;
|
||||||
|
debug_stats m_debugstats;
|
||||||
|
std::string m_debugstatstext;
|
||||||
|
|
||||||
glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f };
|
glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
glm::vec4 m_shadowcolor { 0.5f, 0.5f, 0.5f, 1.f };
|
glm::vec4 m_shadowcolor { 0.65f, 0.65f, 0.65f, 1.f };
|
||||||
float m_specularopaquescalefactor { 1.f };
|
float m_specularopaquescalefactor { 1.f };
|
||||||
float m_speculartranslucentscalefactor { 1.f };
|
float m_speculartranslucentscalefactor { 1.f };
|
||||||
bool m_renderspecular{ false }; // controls whether to include specular component in the calculations
|
bool m_renderspecular{ false }; // controls whether to include specular component in the calculations
|
||||||
|
|
||||||
renderpass_config m_renderpass;
|
renderpass_config m_renderpass;
|
||||||
std::vector<distancesubcell_pair> m_drawqueue; // list of subcells to be drawn in current render pass
|
section_sequence m_sectionqueue; // list of sections in current render pass
|
||||||
|
cell_sequence m_cellqueue;
|
||||||
std::vector<TGroundNode const *> m_picksceneryitems;
|
|
||||||
std::vector<TSubModel const *> m_pickcontrolsitems;
|
std::vector<TSubModel const *> m_pickcontrolsitems;
|
||||||
TSubModel const *m_pickcontrolitem { nullptr };
|
TSubModel const *m_pickcontrolitem { nullptr };
|
||||||
TGroundNode const *m_picksceneryitem { nullptr };
|
std::vector<editor::basic_node const *> m_picksceneryitems;
|
||||||
|
editor::basic_node const *m_picksceneryitem { nullptr };
|
||||||
#ifdef EU07_USE_DEBUG_CAMERA
|
#ifdef EU07_USE_DEBUG_CAMERA
|
||||||
renderpass_config m_worldcamera; // debug item
|
renderpass_config m_worldcamera; // debug item
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Microsoft Visual C++ generated include file.
|
// Microsoft Visual C++ generated include file.
|
||||||
// Used by maszyna.rc
|
// Used by maszyna.rc
|
||||||
//
|
//
|
||||||
#define IDI_ICON1 101
|
//#define GLFW_ICON 101
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
|
|||||||
347
scene.h
Normal file
347
scene.h
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
|
#include <array>
|
||||||
|
#include <stack>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
#include "openglgeometrybank.h"
|
||||||
|
#include "scenenode.h"
|
||||||
|
#include "Track.h"
|
||||||
|
#include "Traction.h"
|
||||||
|
|
||||||
|
class opengl_renderer;
|
||||||
|
namespace scene {
|
||||||
|
|
||||||
|
int const EU07_CELLSIZE = 250;
|
||||||
|
int const EU07_SECTIONSIZE = 1000;
|
||||||
|
int const EU07_REGIONSIDESECTIONCOUNT = 500; // number of sections along a side of square region
|
||||||
|
|
||||||
|
struct scratch_data {
|
||||||
|
|
||||||
|
struct binary_data {
|
||||||
|
|
||||||
|
bool terrain{ false };
|
||||||
|
} binary;
|
||||||
|
|
||||||
|
struct location_data {
|
||||||
|
|
||||||
|
std::stack<glm::dvec3> offset;
|
||||||
|
glm::vec3 rotation;
|
||||||
|
} location;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
bool initialized { false };
|
||||||
|
};
|
||||||
|
|
||||||
|
// basic element of rudimentary partitioning scheme for the section. fixed size, no further subdivision
|
||||||
|
// TBD, TODO: replace with quadtree scheme?
|
||||||
|
class basic_cell {
|
||||||
|
|
||||||
|
friend class ::opengl_renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// methods
|
||||||
|
// legacy method, updates sounds and polls event launchers within radius around specified point
|
||||||
|
void
|
||||||
|
update();
|
||||||
|
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||||
|
void
|
||||||
|
update_traction( TDynamicObject *Vehicle, int const Pantographindex );
|
||||||
|
// legacy method, triggers radio-stop procedure for all vehicles located on paths in the cell
|
||||||
|
void
|
||||||
|
radio_stop();
|
||||||
|
// legacy method, adds specified path to the list of pieces undergoing state change
|
||||||
|
bool
|
||||||
|
RaTrackAnimAdd( TTrack *Track );
|
||||||
|
// legacy method, updates geometry for pieces in the animation list
|
||||||
|
void
|
||||||
|
RaAnimate( unsigned int const Framestamp );
|
||||||
|
// adds provided shape to the cell
|
||||||
|
void
|
||||||
|
insert( shape_node Shape );
|
||||||
|
// adds provided lines to the cell
|
||||||
|
void
|
||||||
|
insert( lines_node Lines );
|
||||||
|
// adds provided path to the cell
|
||||||
|
void
|
||||||
|
insert( TTrack *Path );
|
||||||
|
// adds provided path to the cell
|
||||||
|
void
|
||||||
|
insert( TTraction *Traction );
|
||||||
|
// adds provided model instance to the cell
|
||||||
|
void
|
||||||
|
insert( TAnimModel *Instance );
|
||||||
|
// adds provided sound instance to the cell
|
||||||
|
void
|
||||||
|
insert( sound *Sound );
|
||||||
|
// adds provided event launcher to the cell
|
||||||
|
void
|
||||||
|
insert( TEventLauncher *Launcher );
|
||||||
|
// registers provided path in the lookup directory of the cell
|
||||||
|
void
|
||||||
|
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. reurns: located vehicle and distance
|
||||||
|
std::tuple<TDynamicObject *, float>
|
||||||
|
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
|
||||||
|
// finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint
|
||||||
|
std::tuple<TTrack *, int>
|
||||||
|
find( glm::dvec3 const &Point, TTrack const *Exclude );
|
||||||
|
// 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 path_sequence = std::vector<TTrack *>;
|
||||||
|
using shapenode_sequence = std::vector<shape_node>;
|
||||||
|
using linesnode_sequence = std::vector<lines_node>;
|
||||||
|
using traction_sequence = std::vector<TTraction *>;
|
||||||
|
using instance_sequence = std::vector<TAnimModel *>;
|
||||||
|
using sound_sequence = std::vector<sound *>;
|
||||||
|
using eventlauncher_sequence = std::vector<TEventLauncher *>;
|
||||||
|
// methods
|
||||||
|
void
|
||||||
|
enclose_area( editor::basic_node *Node );
|
||||||
|
// members
|
||||||
|
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE ) };
|
||||||
|
bool m_active { false }; // whether the cell holds any actual data
|
||||||
|
// content
|
||||||
|
shapenode_sequence m_shapesopaque; // opaque pieces of geometry
|
||||||
|
shapenode_sequence m_shapestranslucent; // translucent pieces of geometry
|
||||||
|
linesnode_sequence m_lines;
|
||||||
|
path_sequence m_paths; // path pieces
|
||||||
|
instance_sequence m_instancesopaque;
|
||||||
|
instance_sequence m_instancetranslucent;
|
||||||
|
traction_sequence m_traction;
|
||||||
|
sound_sequence m_sounds;
|
||||||
|
eventlauncher_sequence m_eventlaunchers;
|
||||||
|
// search helpers
|
||||||
|
struct lookup_data {
|
||||||
|
path_sequence paths;
|
||||||
|
traction_sequence traction;
|
||||||
|
} m_directories;
|
||||||
|
// animation of owned items (legacy code, clean up along with track refactoring)
|
||||||
|
bool m_geometrycreated { false };
|
||||||
|
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
||||||
|
TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji
|
||||||
|
};
|
||||||
|
|
||||||
|
// basic scene partitioning structure, holds terrain geometry and collection of cells
|
||||||
|
class basic_section {
|
||||||
|
|
||||||
|
friend class ::opengl_renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// methods
|
||||||
|
// legacy method, updates sounds and polls event launchers within radius around specified point
|
||||||
|
void
|
||||||
|
update( glm::dvec3 const &Location, float const Radius );
|
||||||
|
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||||
|
void
|
||||||
|
update_traction( TDynamicObject *Vehicle, int const Pantographindex );
|
||||||
|
// legacy method, triggers radio-stop procedure for all vehicles in 2km radius around specified location
|
||||||
|
void
|
||||||
|
radio_stop( glm::dvec3 const &Location, float const Radius );
|
||||||
|
// adds provided shape to the section
|
||||||
|
void
|
||||||
|
insert( shape_node Shape );
|
||||||
|
// adds provided lines to the section
|
||||||
|
void
|
||||||
|
insert( lines_node Lines );
|
||||||
|
// adds provided node to the section
|
||||||
|
template <class Type_>
|
||||||
|
void
|
||||||
|
insert( Type_ *Node ) {
|
||||||
|
auto &targetcell { cell( Node->location() ) };
|
||||||
|
targetcell.insert( Node );
|
||||||
|
// some node types can extend bounding area of the target cell
|
||||||
|
m_area.radius = std::max(
|
||||||
|
m_area.radius,
|
||||||
|
static_cast<float>( glm::length( m_area.center - targetcell.area().center ) + targetcell.area().radius ) ); }
|
||||||
|
// registers provided node in the lookup directory of the section enclosing specified point
|
||||||
|
template <class Type_>
|
||||||
|
void
|
||||||
|
register_node( Type_ *Node, glm::dvec3 const &Point ) {
|
||||||
|
cell( Point ).register_end( Node ); }
|
||||||
|
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
|
||||||
|
std::tuple<TDynamicObject *, float>
|
||||||
|
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
|
||||||
|
// finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint
|
||||||
|
std::tuple<TTrack *, int>
|
||||||
|
find( glm::dvec3 const &Point, TTrack const *Exclude );
|
||||||
|
// 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
|
||||||
|
using cell_array = std::array<basic_cell, (EU07_SECTIONSIZE / EU07_CELLSIZE) * (EU07_SECTIONSIZE / EU07_CELLSIZE)>;
|
||||||
|
using shapenode_sequence = std::vector<shape_node>;
|
||||||
|
// methods
|
||||||
|
// provides access to section enclosing specified point
|
||||||
|
basic_cell &
|
||||||
|
cell( glm::dvec3 const &Location );
|
||||||
|
// members
|
||||||
|
// placement and visibility
|
||||||
|
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_SECTIONSIZE ) };
|
||||||
|
// content
|
||||||
|
cell_array m_cells; // partitioning scheme
|
||||||
|
shapenode_sequence m_shapes; // large pieces of opaque geometry and (legacy) terrain
|
||||||
|
// TODO: implement dedicated, higher fidelity, fixed resolution terrain mesh item
|
||||||
|
// gfx renderer data
|
||||||
|
geometrybank_handle m_geometrybank;
|
||||||
|
bool m_geometrycreated { false };
|
||||||
|
};
|
||||||
|
|
||||||
|
// top-level of scene spatial structure, holds collection of sections
|
||||||
|
class basic_region {
|
||||||
|
|
||||||
|
friend class ::opengl_renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
basic_region();
|
||||||
|
// destructor
|
||||||
|
~basic_region();
|
||||||
|
// methods
|
||||||
|
// legacy method, updates sounds and polls event launchers around camera
|
||||||
|
void
|
||||||
|
update();
|
||||||
|
// legacy method, finds and assigns traction piece to specified pantograph of provided vehicle
|
||||||
|
void
|
||||||
|
update_traction( TDynamicObject *Vehicle, int const Pantographindex );
|
||||||
|
// stores content of the class in file with specified name
|
||||||
|
void
|
||||||
|
serialize( std::string const &Scenariofile );
|
||||||
|
// restores content of the class from file with specified name. returns: true on success, false otherwise
|
||||||
|
bool
|
||||||
|
deserialize( std::string const &Scenariofile );
|
||||||
|
// legacy method, links specified path piece with potential neighbours
|
||||||
|
void
|
||||||
|
TrackJoin( TTrack *Track );
|
||||||
|
// legacy method, triggers radio-stop procedure for all vehicles in 2km radius around specified location
|
||||||
|
void
|
||||||
|
RadioStop( glm::dvec3 const &Location );
|
||||||
|
// inserts provided shape in the region
|
||||||
|
void
|
||||||
|
insert_shape( shape_node Shape, scratch_data &Scratchpad, bool const Transform );
|
||||||
|
// inserts provided lines in the region
|
||||||
|
void
|
||||||
|
insert_lines( lines_node Lines, scratch_data &Scratchpad );
|
||||||
|
// inserts provided track in the region
|
||||||
|
void
|
||||||
|
insert_path( TTrack *Path, const scratch_data &Scratchpad );
|
||||||
|
// inserts provided track in the region
|
||||||
|
void
|
||||||
|
insert_traction( TTraction *Traction, scratch_data &Scratchpad );
|
||||||
|
// 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( sound *Sound, scratch_data &Scratchpad );
|
||||||
|
// inserts provided event launcher in the region
|
||||||
|
void
|
||||||
|
insert_launcher( TEventLauncher *Launcher, scratch_data &Scratchpad );
|
||||||
|
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
|
||||||
|
std::tuple<TDynamicObject *, float>
|
||||||
|
find_vehicle( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler );
|
||||||
|
// finds a path with one of its ends located in specified point. returns: located path and id of the matching endpoint
|
||||||
|
std::tuple<TTrack *, int>
|
||||||
|
find_path( glm::dvec3 const &Point, TTrack const *Exclude );
|
||||||
|
// 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 );
|
||||||
|
// 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
|
||||||
|
basic_section &
|
||||||
|
section( glm::dvec3 const &Location );
|
||||||
|
|
||||||
|
// members
|
||||||
|
section_array m_sections;
|
||||||
|
region_scratchpad m_scratchpad;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // scene
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
519
scenenode.cpp
Normal file
519
scenenode.cpp
Normal file
@@ -0,0 +1,519 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "scenenode.h"
|
||||||
|
|
||||||
|
#include "renderer.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
|
||||||
|
namespace scene {
|
||||||
|
|
||||||
|
// restores content of the node from provded input stream
|
||||||
|
shape_node &
|
||||||
|
shape_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
|
// import common data
|
||||||
|
m_name = Nodedata.name;
|
||||||
|
m_data.rangesquared_min = Nodedata.range_min * Nodedata.range_min;
|
||||||
|
m_data.rangesquared_max = (
|
||||||
|
Nodedata.range_max >= 0.0 ?
|
||||||
|
Nodedata.range_max * Nodedata.range_max :
|
||||||
|
std::numeric_limits<double>::max() );
|
||||||
|
|
||||||
|
std::string token = Input.getToken<std::string>();
|
||||||
|
if( token == "material" ) {
|
||||||
|
// lighting settings
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
while( token != "endmaterial" ) {
|
||||||
|
|
||||||
|
if( token == "ambient:" ) {
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> m_data.lighting.ambient.r
|
||||||
|
>> m_data.lighting.ambient.g
|
||||||
|
>> m_data.lighting.ambient.b;
|
||||||
|
m_data.lighting.ambient /= 255.f;
|
||||||
|
m_data.lighting.ambient.a = 1.f;
|
||||||
|
}
|
||||||
|
else if( token == "diffuse:" ) {
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> m_data.lighting.diffuse.r
|
||||||
|
>> m_data.lighting.diffuse.g
|
||||||
|
>> m_data.lighting.diffuse.b;
|
||||||
|
m_data.lighting.diffuse /= 255.f;
|
||||||
|
m_data.lighting.diffuse.a = 1.f;
|
||||||
|
}
|
||||||
|
else if( token == "specular:" ) {
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> m_data.lighting.specular.r
|
||||||
|
>> m_data.lighting.specular.g
|
||||||
|
>> m_data.lighting.specular.b;
|
||||||
|
m_data.lighting.specular /= 255.f;
|
||||||
|
m_data.lighting.specular.a = 1.f;
|
||||||
|
}
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
}
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// assigned material
|
||||||
|
m_data.material = GfxRenderer.Fetch_Material( token );
|
||||||
|
|
||||||
|
// determine way to proceed from the assigned diffuse texture
|
||||||
|
// TBT, TODO: add methods to material manager to access these simpler
|
||||||
|
auto const texturehandle = (
|
||||||
|
m_data.material != null_handle ?
|
||||||
|
GfxRenderer.Material( m_data.material ).texture1 :
|
||||||
|
null_handle );
|
||||||
|
auto const &texture = (
|
||||||
|
texturehandle ?
|
||||||
|
GfxRenderer.Texture( texturehandle ) :
|
||||||
|
opengl_texture() ); // dirty workaround for lack of better api
|
||||||
|
bool const clamps = (
|
||||||
|
texturehandle ?
|
||||||
|
texture.traits.find( 's' ) != std::string::npos :
|
||||||
|
false );
|
||||||
|
bool const clampt = (
|
||||||
|
texturehandle ?
|
||||||
|
texture.traits.find( 't' ) != std::string::npos :
|
||||||
|
false );
|
||||||
|
|
||||||
|
// remainder of legacy 'problend' system -- geometry assigned a texture with '@' in its name is treated as translucent, opaque otherwise
|
||||||
|
if( texturehandle != null_handle ) {
|
||||||
|
m_data.translucent = (
|
||||||
|
( ( texture.name.find( '@' ) != std::string::npos )
|
||||||
|
&& ( true == texture.has_alpha ) ) ?
|
||||||
|
true :
|
||||||
|
false );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_data.translucent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// geometry
|
||||||
|
enum subtype {
|
||||||
|
triangles,
|
||||||
|
triangle_strip,
|
||||||
|
triangle_fan
|
||||||
|
} const nodetype = (
|
||||||
|
Nodedata.type == "triangles" ? triangles :
|
||||||
|
Nodedata.type == "triangle_strip" ? triangle_strip :
|
||||||
|
triangle_fan );
|
||||||
|
std::size_t vertexcount{ 0 };
|
||||||
|
world_vertex vertex, vertex1, vertex2;
|
||||||
|
do {
|
||||||
|
Input.getTokens( 8, false );
|
||||||
|
Input
|
||||||
|
>> vertex.position.x
|
||||||
|
>> vertex.position.y
|
||||||
|
>> vertex.position.z
|
||||||
|
>> vertex.normal.x
|
||||||
|
>> vertex.normal.y
|
||||||
|
>> vertex.normal.z
|
||||||
|
>> vertex.texture.s
|
||||||
|
>> vertex.texture.t;
|
||||||
|
// clamp texture coordinates if texture wrapping is off
|
||||||
|
if( true == clamps ) { vertex.texture.s = clamp( vertex.texture.s, 0.001f, 0.999f ); }
|
||||||
|
if( true == clampt ) { vertex.texture.t = clamp( vertex.texture.t, 0.001f, 0.999f ); }
|
||||||
|
// convert all data to gl_triangles to allow data merge for matching nodes
|
||||||
|
switch( nodetype ) {
|
||||||
|
case triangles: {
|
||||||
|
|
||||||
|
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||||
|
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||||
|
else if( vertexcount >= 2 ) {
|
||||||
|
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
m_data.vertices.emplace_back( vertex2 );
|
||||||
|
m_data.vertices.emplace_back( vertex );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog(
|
||||||
|
"Bad geometry: degenerate triangle encountered"
|
||||||
|
+ ( m_name != "" ? " in node \"" + m_name + "\"" : "" )
|
||||||
|
+ " (vertices: " + to_string( vertex1.position ) + " + " + to_string( vertex2.position ) + " + " + to_string( vertex.position ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++vertexcount;
|
||||||
|
if( vertexcount > 2 ) { vertexcount = 0; } // start new triangle if needed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case triangle_fan: {
|
||||||
|
|
||||||
|
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||||
|
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||||
|
else if( vertexcount >= 2 ) {
|
||||||
|
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
m_data.vertices.emplace_back( vertex2 );
|
||||||
|
m_data.vertices.emplace_back( vertex );
|
||||||
|
vertex2 = vertex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog(
|
||||||
|
"Bad geometry: degenerate triangle encountered"
|
||||||
|
+ ( m_name != "" ? " in node \"" + m_name + "\"" : "" )
|
||||||
|
+ " (vertices: " + to_string( vertex1.position ) + " + " + to_string( vertex2.position ) + " + " + to_string( vertex.position ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++vertexcount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case triangle_strip: {
|
||||||
|
|
||||||
|
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||||
|
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||||
|
else if( vertexcount >= 2 ) {
|
||||||
|
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||||
|
// swap order every other triangle, to maintain consistent winding
|
||||||
|
if( vertexcount % 2 == 0 ) {
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
m_data.vertices.emplace_back( vertex2 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_data.vertices.emplace_back( vertex2 );
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
}
|
||||||
|
m_data.vertices.emplace_back( vertex );
|
||||||
|
|
||||||
|
vertex1 = vertex2;
|
||||||
|
vertex2 = vertex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog(
|
||||||
|
"Bad geometry: degenerate triangle encountered"
|
||||||
|
+ ( m_name != "" ? " in node \"" + m_name + "\"" : "" )
|
||||||
|
+ " (vertices: " + to_string( vertex1.position ) + " + " + to_string( vertex2.position ) + " + " + to_string( vertex.position ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++vertexcount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
|
||||||
|
} while( token != "endtri" );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// imports data from provided submodel
|
||||||
|
shape_node &
|
||||||
|
shape_node::convert( TSubModel const *Submodel ) {
|
||||||
|
|
||||||
|
m_name = Submodel->pName;
|
||||||
|
m_data.lighting.ambient = Submodel->f4Ambient;
|
||||||
|
m_data.lighting.diffuse = Submodel->f4Diffuse;
|
||||||
|
m_data.lighting.specular = Submodel->f4Specular;
|
||||||
|
m_data.material = Submodel->m_material;
|
||||||
|
m_data.translucent = ( true == GfxRenderer.Material( m_data.material ).has_alpha );
|
||||||
|
// NOTE: we set unlimited view range typical for terrain, because we don't expect to convert any other 3d models
|
||||||
|
m_data.rangesquared_max = std::numeric_limits<double>::max();
|
||||||
|
|
||||||
|
if( Submodel->m_geometry == null_handle ) { return *this; }
|
||||||
|
|
||||||
|
int vertexcount { 0 };
|
||||||
|
std::vector<world_vertex> importedvertices;
|
||||||
|
world_vertex vertex, vertex1, vertex2;
|
||||||
|
for( auto const &sourcevertex : GfxRenderer.Vertices( Submodel->m_geometry ) ) {
|
||||||
|
vertex.position = sourcevertex.position;
|
||||||
|
vertex.normal = sourcevertex.normal;
|
||||||
|
vertex.texture = sourcevertex.texture;
|
||||||
|
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||||
|
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||||
|
else if( vertexcount >= 2 ) {
|
||||||
|
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||||
|
importedvertices.emplace_back( vertex1 );
|
||||||
|
importedvertices.emplace_back( vertex2 );
|
||||||
|
importedvertices.emplace_back( vertex );
|
||||||
|
}
|
||||||
|
// start a new triangle
|
||||||
|
vertexcount = -1;
|
||||||
|
}
|
||||||
|
++vertexcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( true == importedvertices.empty() ) { return *this; }
|
||||||
|
|
||||||
|
// assign imported geometry to the node...
|
||||||
|
m_data.vertices.swap( importedvertices );
|
||||||
|
// ...and calculate center...
|
||||||
|
for( auto const &vertex : m_data.vertices ) {
|
||||||
|
m_data.area.center += vertex.position;
|
||||||
|
}
|
||||||
|
m_data.area.center /= m_data.vertices.size();
|
||||||
|
// ...and bounding area
|
||||||
|
double squareradius { 0.0 };
|
||||||
|
for( auto const &vertex : m_data.vertices ) {
|
||||||
|
squareradius = std::max(
|
||||||
|
squareradius,
|
||||||
|
glm::length2( vertex.position - m_data.area.center ) );
|
||||||
|
}
|
||||||
|
m_data.area.radius = std::max(
|
||||||
|
m_data.area.radius,
|
||||||
|
static_cast<float>( std::sqrt( squareradius ) ) );
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||||
|
bool
|
||||||
|
shape_node::merge( shape_node &Shape ) {
|
||||||
|
|
||||||
|
if( ( m_data.material != Shape.m_data.material )
|
||||||
|
|| ( m_data.lighting != Shape.m_data.lighting ) ) {
|
||||||
|
// can't merge nodes with different appearance
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// add geometry from provided node
|
||||||
|
m_data.area.center =
|
||||||
|
interpolate(
|
||||||
|
m_data.area.center, Shape.m_data.area.center,
|
||||||
|
static_cast<float>( Shape.m_data.vertices.size() ) / ( Shape.m_data.vertices.size() + m_data.vertices.size() ) );
|
||||||
|
m_data.vertices.insert(
|
||||||
|
std::end( m_data.vertices ),
|
||||||
|
std::begin( Shape.m_data.vertices ), std::end( Shape.m_data.vertices ) );
|
||||||
|
// NOTE: we could recalculate radius with something other than brute force, but it'll do
|
||||||
|
compute_radius();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||||
|
void
|
||||||
|
shape_node::create_geometry( geometrybank_handle const &Bank ) {
|
||||||
|
|
||||||
|
vertex_array vertices; vertices.reserve( m_data.vertices.size() );
|
||||||
|
|
||||||
|
for( auto const &vertex : m_data.vertices ) {
|
||||||
|
vertices.emplace_back(
|
||||||
|
vertex.position - m_data.origin,
|
||||||
|
vertex.normal,
|
||||||
|
vertex.texture );
|
||||||
|
}
|
||||||
|
m_data.geometry = GfxRenderer.Insert( vertices, Bank, GL_TRIANGLES );
|
||||||
|
std::vector<world_vertex>().swap( m_data.vertices ); // hipster shrink_to_fit
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculates shape's bounding radius
|
||||||
|
void
|
||||||
|
shape_node::compute_radius() {
|
||||||
|
|
||||||
|
auto squaredradius { 0.0 };
|
||||||
|
for( auto const &vertex : m_data.vertices ) {
|
||||||
|
squaredradius = std::max(
|
||||||
|
squaredradius,
|
||||||
|
glm::length2( vertex.position - m_data.area.center ) );
|
||||||
|
}
|
||||||
|
m_data.area.radius = static_cast<float>( std::sqrt( squaredradius ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// restores content of the node from provded input stream
|
||||||
|
lines_node &
|
||||||
|
lines_node::deserialize( cParser &Input, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
|
// import common data
|
||||||
|
m_name = Nodedata.name;
|
||||||
|
m_data.rangesquared_min = Nodedata.range_min * Nodedata.range_min;
|
||||||
|
m_data.rangesquared_max = (
|
||||||
|
Nodedata.range_max >= 0.0 ?
|
||||||
|
Nodedata.range_max * Nodedata.range_max :
|
||||||
|
std::numeric_limits<double>::max() );
|
||||||
|
|
||||||
|
// material
|
||||||
|
Input.getTokens( 3, false );
|
||||||
|
Input
|
||||||
|
>> m_data.lighting.diffuse.r
|
||||||
|
>> m_data.lighting.diffuse.g
|
||||||
|
>> m_data.lighting.diffuse.b;
|
||||||
|
m_data.lighting.diffuse /= 255.f;
|
||||||
|
m_data.lighting.diffuse.a = 1.f;
|
||||||
|
Input.getTokens( 1, false );
|
||||||
|
Input
|
||||||
|
>> m_data.line_width;
|
||||||
|
m_data.line_width = std::min( 30.f, m_data.line_width ); // 30 pix equals rougly width of a signal pole viewed from ~1m away
|
||||||
|
|
||||||
|
// geometry
|
||||||
|
enum subtype {
|
||||||
|
lines,
|
||||||
|
line_strip,
|
||||||
|
line_loop
|
||||||
|
} const nodetype = (
|
||||||
|
Nodedata.type == "lines" ? lines :
|
||||||
|
Nodedata.type == "line_strip" ? line_strip :
|
||||||
|
line_loop );
|
||||||
|
std::size_t vertexcount { 0 };
|
||||||
|
world_vertex vertex, vertex0, vertex1;
|
||||||
|
std::string token = Input.getToken<std::string>();
|
||||||
|
do {
|
||||||
|
vertex.position.x = std::atof( token.c_str() );
|
||||||
|
Input.getTokens( 2, false );
|
||||||
|
Input
|
||||||
|
>> vertex.position.y
|
||||||
|
>> vertex.position.z;
|
||||||
|
// convert all data to gl_lines to allow data merge for matching nodes
|
||||||
|
switch( nodetype ) {
|
||||||
|
case lines: {
|
||||||
|
m_data.vertices.emplace_back( vertex );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case line_strip: {
|
||||||
|
if( vertexcount > 0 ) {
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
m_data.vertices.emplace_back( vertex );
|
||||||
|
}
|
||||||
|
vertex1 = vertex;
|
||||||
|
++vertexcount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case line_loop: {
|
||||||
|
if( vertexcount == 0 ) {
|
||||||
|
vertex0 = vertex;
|
||||||
|
vertex1 = vertex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
m_data.vertices.emplace_back( vertex );
|
||||||
|
}
|
||||||
|
vertex1 = vertex;
|
||||||
|
++vertexcount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
|
||||||
|
} while( token != "endline" );
|
||||||
|
// add closing line for the loop
|
||||||
|
if( ( nodetype == line_loop )
|
||||||
|
&& ( vertexcount > 2 ) ) {
|
||||||
|
m_data.vertices.emplace_back( vertex1 );
|
||||||
|
m_data.vertices.emplace_back( vertex0 );
|
||||||
|
}
|
||||||
|
if( m_data.vertices.size() % 2 != 0 ) {
|
||||||
|
ErrorLog( "Lines node specified odd number of vertices, encountered in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
|
||||||
|
m_data.vertices.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||||
|
bool
|
||||||
|
lines_node::merge( lines_node &Lines ) {
|
||||||
|
|
||||||
|
if( ( m_data.line_width != Lines.m_data.line_width )
|
||||||
|
|| ( m_data.lighting != Lines.m_data.lighting ) ) {
|
||||||
|
// can't merge nodes with different appearance
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// add geometry from provided node
|
||||||
|
m_data.area.center =
|
||||||
|
interpolate(
|
||||||
|
m_data.area.center, Lines.m_data.area.center,
|
||||||
|
static_cast<float>( Lines.m_data.vertices.size() ) / ( Lines.m_data.vertices.size() + m_data.vertices.size() ) );
|
||||||
|
m_data.vertices.insert(
|
||||||
|
std::end( m_data.vertices ),
|
||||||
|
std::begin( Lines.m_data.vertices ), std::end( Lines.m_data.vertices ) );
|
||||||
|
// NOTE: we could recalculate radius with something other than brute force, but it'll do
|
||||||
|
compute_radius();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||||
|
void
|
||||||
|
lines_node::create_geometry( geometrybank_handle const &Bank ) {
|
||||||
|
|
||||||
|
vertex_array vertices; vertices.reserve( m_data.vertices.size() );
|
||||||
|
|
||||||
|
for( auto const &vertex : m_data.vertices ) {
|
||||||
|
vertices.emplace_back(
|
||||||
|
vertex.position - m_data.origin,
|
||||||
|
vertex.normal,
|
||||||
|
vertex.texture );
|
||||||
|
}
|
||||||
|
m_data.geometry = GfxRenderer.Insert( vertices, Bank, GL_LINES );
|
||||||
|
std::vector<world_vertex>().swap( m_data.vertices ); // hipster shrink_to_fit
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculates node's bounding radius
|
||||||
|
void
|
||||||
|
lines_node::compute_radius() {
|
||||||
|
|
||||||
|
auto squaredradius { 0.0 };
|
||||||
|
for( auto const &vertex : m_data.vertices ) {
|
||||||
|
squaredradius = std::max(
|
||||||
|
squaredradius,
|
||||||
|
glm::length2( vertex.position - m_data.area.center ) );
|
||||||
|
}
|
||||||
|
m_data.area.radius = static_cast<float>( std::sqrt( squaredradius ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
memory_node &
|
||||||
|
memory_node::deserialize( cParser &Input, node_data const &Nodedata ) {
|
||||||
|
|
||||||
|
// import common data
|
||||||
|
m_name = Nodedata.name;
|
||||||
|
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> m_data.area.center.x
|
||||||
|
>> m_data.area.center.y
|
||||||
|
>> m_data.area.center.z;
|
||||||
|
|
||||||
|
TMemCell memorycell( Nodedata.name );
|
||||||
|
memorycell.Load( &Input );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} // scene
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace editor {
|
||||||
|
|
||||||
|
basic_node::basic_node( scene::node_data const &Nodedata ) :
|
||||||
|
m_name( Nodedata.name )
|
||||||
|
{
|
||||||
|
m_rangesquaredmin = Nodedata.range_min * Nodedata.range_min;
|
||||||
|
m_rangesquaredmax = (
|
||||||
|
Nodedata.range_max >= 0.0 ?
|
||||||
|
Nodedata.range_max * Nodedata.range_max :
|
||||||
|
std::numeric_limits<double>::max() );
|
||||||
|
}
|
||||||
|
|
||||||
|
float const &
|
||||||
|
basic_node::radius() {
|
||||||
|
|
||||||
|
if( m_area.radius == -1.0 ) {
|
||||||
|
// calculate if needed
|
||||||
|
radius_();
|
||||||
|
}
|
||||||
|
return m_area.radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
// by default nodes are 'virtual don't extend from their center point
|
||||||
|
void
|
||||||
|
basic_node::radius_() {
|
||||||
|
|
||||||
|
m_area.radius = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // editor
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
318
scenenode.h
Normal file
318
scenenode.h
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "material.h"
|
||||||
|
#include "vertex.h"
|
||||||
|
#include "openglgeometrybank.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "Model3d.h"
|
||||||
|
|
||||||
|
struct lighting_data {
|
||||||
|
|
||||||
|
glm::vec4 diffuse { 0.8f, 0.8f, 0.8f, 1.0f };
|
||||||
|
glm::vec4 ambient { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||||
|
glm::vec4 specular { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator==( lighting_data const &Left, lighting_data const &Right ) {
|
||||||
|
return ( ( Left.diffuse == Right.diffuse )
|
||||||
|
&& ( Left.ambient == Right.ambient )
|
||||||
|
&& ( Left.specular == Right.specular ) ); }
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator!=( lighting_data const &Left, lighting_data const &Right ) {
|
||||||
|
return !( Left == Right ); }
|
||||||
|
|
||||||
|
namespace scene {
|
||||||
|
|
||||||
|
struct bounding_area {
|
||||||
|
|
||||||
|
glm::dvec3 center; // mid point of the rectangle
|
||||||
|
float radius { -1.0f }; // radius of the bounding sphere
|
||||||
|
|
||||||
|
bounding_area() = default;
|
||||||
|
bounding_area( glm::dvec3 Center, float Radius ) :
|
||||||
|
center( Center ),
|
||||||
|
radius( Radius )
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
enum nodetype {
|
||||||
|
|
||||||
|
unknown,
|
||||||
|
model,
|
||||||
|
triangles,
|
||||||
|
lines,
|
||||||
|
dynamic,
|
||||||
|
track,
|
||||||
|
traction,
|
||||||
|
powersource,
|
||||||
|
sound,
|
||||||
|
memorycell,
|
||||||
|
eventlauncher
|
||||||
|
};
|
||||||
|
|
||||||
|
class node_manager {
|
||||||
|
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct node_data {
|
||||||
|
|
||||||
|
double range_min { 0.0 };
|
||||||
|
double range_max { std::numeric_limits<double>::max() };
|
||||||
|
std::string name;
|
||||||
|
std::string type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// holds unique piece of geometry, covered with single material
|
||||||
|
class shape_node {
|
||||||
|
|
||||||
|
friend class basic_region; // region might want to modify node content when it's being inserted
|
||||||
|
|
||||||
|
public:
|
||||||
|
// types
|
||||||
|
struct shapenode_data {
|
||||||
|
// placement and visibility
|
||||||
|
scene::bounding_area area; // bounding area, in world coordinates
|
||||||
|
bool visible { true }; // visibility flag
|
||||||
|
double rangesquared_min { 0.0 }; // visibility range, min
|
||||||
|
double rangesquared_max { 0.0 }; // visibility range, max
|
||||||
|
// material data
|
||||||
|
material_handle material { 0 };
|
||||||
|
lighting_data lighting;
|
||||||
|
bool translucent { false }; // whether opaque or translucent
|
||||||
|
// geometry data
|
||||||
|
std::vector<world_vertex> vertices; // world space source data of the geometry
|
||||||
|
glm::dvec3 origin; // world position of the relative coordinate system origin
|
||||||
|
geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer
|
||||||
|
};
|
||||||
|
|
||||||
|
// methods
|
||||||
|
// restores content of the node from provded input stream
|
||||||
|
shape_node &
|
||||||
|
deserialize( cParser &Input, scene::node_data const &Nodedata );
|
||||||
|
// imports data from provided submodel
|
||||||
|
shape_node &
|
||||||
|
convert( TSubModel const *Submodel );
|
||||||
|
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||||
|
bool
|
||||||
|
merge( shape_node &Shape );
|
||||||
|
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||||
|
void
|
||||||
|
create_geometry( geometrybank_handle const &Bank );
|
||||||
|
// calculates shape's bounding radius
|
||||||
|
void
|
||||||
|
compute_radius();
|
||||||
|
// set visibility
|
||||||
|
void
|
||||||
|
visible( bool State ) {
|
||||||
|
m_data.visible = State; }
|
||||||
|
// set origin point
|
||||||
|
void
|
||||||
|
origin( glm::dvec3 Origin ) {
|
||||||
|
m_data.origin = Origin; }
|
||||||
|
// data access
|
||||||
|
shapenode_data const &
|
||||||
|
data() const {
|
||||||
|
return m_data; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// members
|
||||||
|
std::string m_name;
|
||||||
|
shapenode_data m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// holds a group of untextured lines
|
||||||
|
class lines_node {
|
||||||
|
|
||||||
|
friend class basic_region; // region might want to modify node content when it's being inserted
|
||||||
|
|
||||||
|
public:
|
||||||
|
// types
|
||||||
|
struct linesnode_data {
|
||||||
|
// placement and visibility
|
||||||
|
scene::bounding_area area; // bounding area, in world coordinates
|
||||||
|
bool visible { true }; // visibility flag
|
||||||
|
double rangesquared_min { 0.0 }; // visibility range, min
|
||||||
|
double rangesquared_max { 0.0 }; // visibility range, max
|
||||||
|
// material data
|
||||||
|
lighting_data lighting;
|
||||||
|
float line_width; // thickness of stored lines
|
||||||
|
// geometry data
|
||||||
|
std::vector<world_vertex> vertices; // world space source data of the geometry
|
||||||
|
glm::dvec3 origin; // world position of the relative coordinate system origin
|
||||||
|
geometry_handle geometry { 0, 0 }; // relative origin-centered chunk of geometry held by gfx renderer
|
||||||
|
};
|
||||||
|
|
||||||
|
// methods
|
||||||
|
// restores content of the node from provded input stream
|
||||||
|
lines_node &
|
||||||
|
deserialize( cParser &Input, scene::node_data const &Nodedata );
|
||||||
|
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||||
|
bool
|
||||||
|
merge( lines_node &Lines );
|
||||||
|
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||||
|
void
|
||||||
|
create_geometry( geometrybank_handle const &Bank );
|
||||||
|
// calculates shape's bounding radius
|
||||||
|
void
|
||||||
|
compute_radius();
|
||||||
|
// set visibility
|
||||||
|
void
|
||||||
|
visible( bool State ) {
|
||||||
|
m_data.visible = State; }
|
||||||
|
// set origin point
|
||||||
|
void
|
||||||
|
origin( glm::dvec3 Origin ) {
|
||||||
|
m_data.origin = Origin; }
|
||||||
|
// data access
|
||||||
|
linesnode_data const &
|
||||||
|
data() const {
|
||||||
|
return m_data; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// members
|
||||||
|
std::string m_name;
|
||||||
|
linesnode_data m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
// holds geometry for specific piece of track/road/waterway
|
||||||
|
class path_node {
|
||||||
|
|
||||||
|
friend class basic_region; // region might want to modify node content when it's being inserted
|
||||||
|
|
||||||
|
public:
|
||||||
|
// types
|
||||||
|
// TODO: enable after track class refactoring
|
||||||
|
struct pathnode_data {
|
||||||
|
// placement and visibility
|
||||||
|
bounding_area area; // bounding area, in world coordinates
|
||||||
|
bool visible { true }; // visibility flag
|
||||||
|
// material data
|
||||||
|
material_handle material_1 { 0 };
|
||||||
|
material_handle material_2 { 0 };
|
||||||
|
lighting_data lighting;
|
||||||
|
TEnvironmentType environment { e_flat };
|
||||||
|
// geometry data
|
||||||
|
std::vector<world_vertex> vertices; // world space source data of the geometry
|
||||||
|
glm::dvec3 origin; // world position of the relative coordinate system origin
|
||||||
|
using geometryhandle_sequence = std::vector<geometry_handle>;
|
||||||
|
geometryhandle_sequence geometry_1; // geometry chunks textured with texture 1
|
||||||
|
geometryhandle_sequence geometry_2; // geometry chunks textured with texture 2
|
||||||
|
};
|
||||||
|
// methods
|
||||||
|
// restores content of the node from provded input stream
|
||||||
|
// TODO: implement
|
||||||
|
path_node &
|
||||||
|
deserialize( cParser &Input, node_data const &Nodedata );
|
||||||
|
// binds specified track to the node
|
||||||
|
// TODO: remove after track class refactoring
|
||||||
|
void
|
||||||
|
path( TTrack *Path ) {
|
||||||
|
m_path = Path; }
|
||||||
|
TTrack *
|
||||||
|
path() {
|
||||||
|
return m_path; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// members
|
||||||
|
|
||||||
|
// // TODO: enable after track class refactoring
|
||||||
|
// pathnode_data m_data;
|
||||||
|
|
||||||
|
TTrack * m_path;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
// holds reference to memory cell
|
||||||
|
class memorycell_node {
|
||||||
|
|
||||||
|
friend class basic_region; // region might want to modify node content when it's being inserted
|
||||||
|
|
||||||
|
public:
|
||||||
|
// types
|
||||||
|
struct memorynode_data {
|
||||||
|
// placement and visibility
|
||||||
|
bounding_area area; // bounding area, in world coordinates
|
||||||
|
bool visible { false }; // visibility flag
|
||||||
|
};
|
||||||
|
// methods
|
||||||
|
// restores content of the node from provded input stream
|
||||||
|
// TODO: implement
|
||||||
|
memory_node &
|
||||||
|
deserialize( cParser &Input, node_data const &Nodedata );
|
||||||
|
void
|
||||||
|
cell( TMemCell *Cell ) {
|
||||||
|
m_memorycell = Cell; }
|
||||||
|
TMemCell *
|
||||||
|
cell() {
|
||||||
|
return m_memorycell; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// members
|
||||||
|
memorynode_data m_data;
|
||||||
|
TMemCell * m_memorycell;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
} // scene
|
||||||
|
|
||||||
|
namespace editor {
|
||||||
|
|
||||||
|
// base interface for nodes which can be actvated in scenario editor
|
||||||
|
struct basic_node {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
basic_node() = default; // TODO: remove after refactor
|
||||||
|
basic_node( scene::node_data const &Nodedata );
|
||||||
|
// destructor
|
||||||
|
virtual ~basic_node() = default;
|
||||||
|
// methods
|
||||||
|
std::string const &
|
||||||
|
name() const {
|
||||||
|
return m_name; }
|
||||||
|
void
|
||||||
|
location( glm::dvec3 const Location ) {
|
||||||
|
m_area.center = Location; }
|
||||||
|
glm::dvec3 const &
|
||||||
|
location() const {
|
||||||
|
return m_area.center; };
|
||||||
|
float const &
|
||||||
|
radius();
|
||||||
|
void
|
||||||
|
visible( bool const Visible ) {
|
||||||
|
m_visible = Visible; }
|
||||||
|
bool
|
||||||
|
visible() const {
|
||||||
|
return m_visible; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// methods
|
||||||
|
// radius() subclass details, calculates node's bounding radius
|
||||||
|
virtual void radius_();
|
||||||
|
// members
|
||||||
|
scene::bounding_area m_area;
|
||||||
|
bool m_visible { true };
|
||||||
|
double m_rangesquaredmin { 0.0 }; // visibility range, min
|
||||||
|
double m_rangesquaredmax { 0.0 }; // visibility range, max
|
||||||
|
std::string m_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // editor
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
876
simulation.cpp
Normal file
876
simulation.cpp
Normal file
@@ -0,0 +1,876 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "simulation.h"
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Logs.h"
|
||||||
|
#include "uilayer.h"
|
||||||
|
|
||||||
|
namespace simulation {
|
||||||
|
|
||||||
|
state_manager State;
|
||||||
|
event_manager Events;
|
||||||
|
memory_table Memory;
|
||||||
|
path_table Paths;
|
||||||
|
traction_table Traction;
|
||||||
|
powergridsource_table Powergrid;
|
||||||
|
instance_table Instances;
|
||||||
|
vehicle_table Vehicles;
|
||||||
|
light_array Lights;
|
||||||
|
lua Lua;
|
||||||
|
|
||||||
|
scene::basic_region *Region { nullptr };
|
||||||
|
|
||||||
|
bool
|
||||||
|
state_manager::deserialize( std::string const &Scenariofile ) {
|
||||||
|
|
||||||
|
// TODO: move initialization to separate routine so we can reuse it
|
||||||
|
SafeDelete( Region );
|
||||||
|
Region = new scene::basic_region();
|
||||||
|
|
||||||
|
// TODO: check first for presence of serialized binary files
|
||||||
|
// if this fails, fall back on the legacy text format
|
||||||
|
scene::scratch_data importscratchpad;
|
||||||
|
importscratchpad.binary.terrain = Region->deserialize( Scenariofile );
|
||||||
|
// NOTE: for the time being import from text format is a given, since we don't have full binary serialization
|
||||||
|
cParser scenarioparser( Scenariofile, cParser::buffer_FILE, Global::asCurrentSceneryPath, Global::bLoadTraction );
|
||||||
|
|
||||||
|
if( false == scenarioparser.ok() ) { return false; }
|
||||||
|
|
||||||
|
deserialize( scenarioparser, importscratchpad );
|
||||||
|
// if we didn't find usable binary version of the scenario files, create them now for future use
|
||||||
|
if( false == importscratchpad.binary.terrain ) { Region->serialize( Scenariofile ); }
|
||||||
|
|
||||||
|
Global::iPause &= ~0x10; // koniec pauzy wczytywania
|
||||||
|
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, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// prepare deserialization function table
|
||||||
|
// since all methods use the same objects, we can have simple, hard-coded binds or lambdas for the task
|
||||||
|
using deserializefunction = void(state_manager::*)(cParser &, scene::scratch_data &);
|
||||||
|
std::vector<
|
||||||
|
std::pair<
|
||||||
|
std::string,
|
||||||
|
deserializefunction> > functionlist = {
|
||||||
|
{ "atmo", &state_manager::deserialize_atmo },
|
||||||
|
{ "camera", &state_manager::deserialize_camera },
|
||||||
|
{ "config", &state_manager::deserialize_config },
|
||||||
|
{ "description", &state_manager::deserialize_description },
|
||||||
|
{ "event", &state_manager::deserialize_event },
|
||||||
|
{ "lua", &state_manager::deserialize_lua },
|
||||||
|
{ "firstinit", &state_manager::deserialize_firstinit },
|
||||||
|
{ "light", &state_manager::deserialize_light },
|
||||||
|
{ "node", &state_manager::deserialize_node },
|
||||||
|
{ "origin", &state_manager::deserialize_origin },
|
||||||
|
{ "endorigin", &state_manager::deserialize_endorigin },
|
||||||
|
{ "rotate", &state_manager::deserialize_rotate },
|
||||||
|
{ "sky", &state_manager::deserialize_sky },
|
||||||
|
{ "test", &state_manager::deserialize_test },
|
||||||
|
{ "time", &state_manager::deserialize_time },
|
||||||
|
{ "trainset", &state_manager::deserialize_trainset },
|
||||||
|
{ "endtrainset", &state_manager::deserialize_endtrainset } };
|
||||||
|
using deserializefunctionbind = std::function<void()>;
|
||||||
|
std::unordered_map<
|
||||||
|
std::string,
|
||||||
|
deserializefunctionbind> functionmap;
|
||||||
|
for( auto &function : functionlist ) {
|
||||||
|
functionmap.emplace( function.first, std::bind( function.second, this, std::ref( Input ), std::ref( Scratchpad ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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() ) {
|
||||||
|
|
||||||
|
auto lookup = functionmap.find( token );
|
||||||
|
if( lookup != functionmap.end() ) {
|
||||||
|
lookup->second();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( false == Scratchpad.initialized ) {
|
||||||
|
// manually perform scenario initialization
|
||||||
|
deserialize_firstinit( Input, Scratchpad );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// NOTE: parameter system needs some decent replacement, but not worth the effort if we're moving to built-in editor
|
||||||
|
// atmosphere color; legacy parameter, no longer used
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
// fog range
|
||||||
|
Input.getTokens( 2 );
|
||||||
|
Input
|
||||||
|
>> Global::fFogStart
|
||||||
|
>> Global::fFogEnd;
|
||||||
|
|
||||||
|
if( Global::fFogEnd > 0.0 ) {
|
||||||
|
// fog colour; optional legacy parameter, no longer used
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string token { Input.getToken<std::string>() };
|
||||||
|
if( token != "endatmo" ) {
|
||||||
|
// optional overcast parameter
|
||||||
|
Global::Overcast = clamp( std::stof( token ), 0.f, 1.f );
|
||||||
|
}
|
||||||
|
while( ( false == token.empty() )
|
||||||
|
&& ( token != "endatmo" ) ) {
|
||||||
|
// anything else left in the section has no defined meaning
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
glm::dvec3 xyz, abc;
|
||||||
|
int i = -1, into = -1; // do której definicji kamery wstawić
|
||||||
|
std::string token;
|
||||||
|
do { // opcjonalna siódma liczba określa numer kamery, a kiedyś były tylko 3
|
||||||
|
Input.getTokens();
|
||||||
|
Input >> token;
|
||||||
|
switch( ++i ) { // kiedyś camera miało tylko 3 współrzędne
|
||||||
|
case 0: { xyz.x = atof( token.c_str() ); break; }
|
||||||
|
case 1: { xyz.y = atof( token.c_str() ); break; }
|
||||||
|
case 2: { xyz.z = atof( token.c_str() ); break; }
|
||||||
|
case 3: { abc.x = atof( token.c_str() ); break; }
|
||||||
|
case 4: { abc.y = atof( token.c_str() ); break; }
|
||||||
|
case 5: { abc.z = atof( token.c_str() ); break; }
|
||||||
|
case 6: { into = atoi( token.c_str() ); break; } // takie sobie, bo można wpisać -1
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
} while( token.compare( "endcamera" ) != 0 );
|
||||||
|
if( into < 0 )
|
||||||
|
into = ++Global::iCameraLast;
|
||||||
|
if( into < 10 ) { // przepisanie do odpowiedniego miejsca w tabelce
|
||||||
|
Global::FreeCameraInit[ into ] = xyz;
|
||||||
|
Global::FreeCameraInitAngle[ into ] =
|
||||||
|
Math3D::vector3(
|
||||||
|
glm::radians( abc.x ),
|
||||||
|
glm::radians( abc.y ),
|
||||||
|
glm::radians( abc.z ) );
|
||||||
|
Global::iCameraLast = into; // numer ostatniej
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// cleaned up version of the above.
|
||||||
|
// NOTE: no longer supports legacy mode where some parameters were optional
|
||||||
|
Input.getTokens( 7 );
|
||||||
|
glm::vec3
|
||||||
|
position,
|
||||||
|
rotation;
|
||||||
|
int index;
|
||||||
|
Input
|
||||||
|
>> position.x
|
||||||
|
>> position.y
|
||||||
|
>> position.z
|
||||||
|
>> rotation.x
|
||||||
|
>> rotation.y
|
||||||
|
>> rotation.z
|
||||||
|
>> index;
|
||||||
|
|
||||||
|
skip_until( Input, "endcamera" );
|
||||||
|
|
||||||
|
// TODO: finish this
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_config( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// config parameters (re)definition
|
||||||
|
Global::ConfigParse( Input );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_description( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// legacy section, never really used;
|
||||||
|
skip_until( Input, "enddescription" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_event( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// TODO: refactor event class and its de/serialization. do offset and rotation after deserialization is done
|
||||||
|
auto *event = new TEvent();
|
||||||
|
Math3D::vector3 offset = (
|
||||||
|
Scratchpad.location.offset.empty() ?
|
||||||
|
Math3D::vector3() :
|
||||||
|
Math3D::vector3(
|
||||||
|
Scratchpad.location.offset.top().x,
|
||||||
|
Scratchpad.location.offset.top().y,
|
||||||
|
Scratchpad.location.offset.top().z ) );
|
||||||
|
event->Load( &Input, offset );
|
||||||
|
|
||||||
|
if( false == simulation::Events.insert( event ) ) {
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void state_manager::deserialize_lua( cParser &Input, scene::scratch_data &Scratchpad )
|
||||||
|
{
|
||||||
|
Input.getTokens(1, false);
|
||||||
|
std::string file;
|
||||||
|
Input >> file;
|
||||||
|
simulation::Lua.interpret(Global::asCurrentSceneryPath + file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_firstinit( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
if( true == Scratchpad.initialized ) { return; }
|
||||||
|
|
||||||
|
simulation::Paths.InitTracks();
|
||||||
|
simulation::Traction.InitTraction();
|
||||||
|
simulation::Events.InitEvents();
|
||||||
|
simulation::Events.InitLaunchers();
|
||||||
|
simulation::Memory.InitCells();
|
||||||
|
|
||||||
|
Scratchpad.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_light( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// legacy section, no longer used nor supported;
|
||||||
|
skip_until( Input, "endlight" );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
Input
|
||||||
|
>> nodedata.range_max
|
||||||
|
>> nodedata.range_min
|
||||||
|
>> nodedata.name
|
||||||
|
>> nodedata.type;
|
||||||
|
// type-based deserialization. not elegant but it'll do
|
||||||
|
if( nodedata.type == "dynamic" ) {
|
||||||
|
|
||||||
|
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 *path { deserialize_path( Input, Scratchpad, nodedata ) };
|
||||||
|
// duplicates of named tracks are currently experimentally allowed
|
||||||
|
if( false == simulation::Paths.insert( path ) ) {
|
||||||
|
ErrorLog( "Bad scenario: track with duplicate name \"" + path->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
/*
|
||||||
|
delete path;
|
||||||
|
delete pathnode;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
simulation::Region->insert_path( path, Scratchpad );
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "traction" ) {
|
||||||
|
|
||||||
|
auto *traction { deserialize_traction( Input, Scratchpad, nodedata ) };
|
||||||
|
// traction loading is optional
|
||||||
|
if( traction == nullptr ) { return; }
|
||||||
|
|
||||||
|
if( false == simulation::Traction.insert( traction ) ) {
|
||||||
|
ErrorLog( "Bad scenario: traction piece with duplicate name \"" + traction->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
simulation::Region->insert_traction( traction, Scratchpad );
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "tractionpowersource" ) {
|
||||||
|
|
||||||
|
auto *powersource { deserialize_tractionpowersource( Input, Scratchpad, nodedata ) };
|
||||||
|
// traction loading is optional
|
||||||
|
if( powersource == nullptr ) { return; }
|
||||||
|
|
||||||
|
if( false == simulation::Powergrid.insert( powersource ) ) {
|
||||||
|
ErrorLog( "Bad scenario: power grid source with duplicate name \"" + powersource->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// TODO: implement this
|
||||||
|
simulation::Region.insert_powersource( powersource, Scratchpad );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "model" ) {
|
||||||
|
|
||||||
|
if( nodedata.range_min < 0.0 ) {
|
||||||
|
// convert and import 3d terrain
|
||||||
|
auto *instance { deserialize_model( Input, Scratchpad, nodedata ) };
|
||||||
|
// model import can potentially fail
|
||||||
|
if( instance == nullptr ) { return; }
|
||||||
|
// go through submodels, and import them as shapes
|
||||||
|
auto const cellcount = instance->TerrainCount() + 1; // zliczenie submodeli
|
||||||
|
for( auto i = 1; i < cellcount; ++i ) {
|
||||||
|
auto *submodel = instance->TerrainSquare( i - 1 );
|
||||||
|
simulation::Region->insert_shape(
|
||||||
|
scene::shape_node().convert( submodel ),
|
||||||
|
Scratchpad,
|
||||||
|
false );
|
||||||
|
// if there's more than one group of triangles in the cell they're held as children of the primary submodel
|
||||||
|
submodel = submodel->ChildGet();
|
||||||
|
while( submodel != nullptr ) {
|
||||||
|
simulation::Region->insert_shape(
|
||||||
|
scene::shape_node().convert( submodel ),
|
||||||
|
Scratchpad,
|
||||||
|
false );
|
||||||
|
submodel = submodel->NextGet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// with the import done we can get rid of the source model
|
||||||
|
delete instance;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// regular instance of 3d mesh
|
||||||
|
auto *instance { deserialize_model( Input, Scratchpad, nodedata ) };
|
||||||
|
// model import can potentially fail
|
||||||
|
if( instance == nullptr ) { return; }
|
||||||
|
|
||||||
|
if( false == simulation::Instances.insert( instance ) ) {
|
||||||
|
ErrorLog( "Bad scenario: 3d model instance with duplicate name \"" + instance->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
simulation::Region->insert_instance( instance, Scratchpad );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ( nodedata.type == "triangles" )
|
||||||
|
|| ( nodedata.type == "triangle_strip" )
|
||||||
|
|| ( nodedata.type == "triangle_fan" ) ) {
|
||||||
|
|
||||||
|
if( false == Scratchpad.binary.terrain ) {
|
||||||
|
|
||||||
|
simulation::Region->insert_shape(
|
||||||
|
scene::shape_node().deserialize(
|
||||||
|
Input, nodedata ),
|
||||||
|
Scratchpad,
|
||||||
|
true );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// all shapes were already loaded from the binary version of the file
|
||||||
|
skip_until( Input, "endtri" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ( nodedata.type == "lines" )
|
||||||
|
|| ( nodedata.type == "line_strip" )
|
||||||
|
|| ( nodedata.type == "line_loop" ) ) {
|
||||||
|
|
||||||
|
if( false == Scratchpad.binary.terrain ) {
|
||||||
|
|
||||||
|
simulation::Region->insert_lines(
|
||||||
|
scene::lines_node().deserialize(
|
||||||
|
Input, nodedata ),
|
||||||
|
Scratchpad );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// all lines were already loaded from the binary version of the file
|
||||||
|
skip_until( Input, "endline" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "memcell" ) {
|
||||||
|
|
||||||
|
auto *memorycell { deserialize_memorycell( Input, Scratchpad, nodedata ) };
|
||||||
|
if( false == simulation::Memory.insert( memorycell ) ) {
|
||||||
|
ErrorLog( "Bad scenario: memory cell with duplicate name \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// TODO: implement this
|
||||||
|
simulation::Region.insert_memorycell( memorycell, Scratchpad );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "eventlauncher" ) {
|
||||||
|
|
||||||
|
auto *eventlauncher { deserialize_eventlauncher( Input, Scratchpad, nodedata ) };
|
||||||
|
if( false == simulation::Events.insert( eventlauncher ) ) {
|
||||||
|
ErrorLog( "Bad scenario: event launcher with duplicate name \"" + eventlauncher->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
// event launchers can be either global, or local with limited range of activation
|
||||||
|
// each gets assigned different caretaker
|
||||||
|
if( true == eventlauncher->IsGlobal() ) {
|
||||||
|
simulation::Events.queue( eventlauncher );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
simulation::Region->insert_launcher( eventlauncher, Scratchpad );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "sound" ) {
|
||||||
|
|
||||||
|
auto *sound { deserialize_sound( Input, Scratchpad, nodedata ) };
|
||||||
|
simulation::Region->insert_sound( sound, Scratchpad );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_origin( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
glm::dvec3 offset;
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> offset.x
|
||||||
|
>> offset.y
|
||||||
|
>> offset.z;
|
||||||
|
// sumowanie całkowitego przesunięcia
|
||||||
|
Scratchpad.location.offset.emplace(
|
||||||
|
offset + (
|
||||||
|
Scratchpad.location.offset.empty() ?
|
||||||
|
glm::dvec3() :
|
||||||
|
Scratchpad.location.offset.top() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_endorigin( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
if( false == Scratchpad.location.offset.empty() ) {
|
||||||
|
Scratchpad.location.offset.pop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad origin: endorigin instruction with empty origin stack in file \"" + Input.Name() + "\" (line " + std::to_string( Input.Line() - 1 ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_rotate( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> Scratchpad.location.rotation.x
|
||||||
|
>> Scratchpad.location.rotation.y
|
||||||
|
>> Scratchpad.location.rotation.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// sky model
|
||||||
|
Input.getTokens( 1 );
|
||||||
|
Input
|
||||||
|
>> Global::asSky;
|
||||||
|
// anything else left in the section has no defined meaning
|
||||||
|
skip_until( Input, "endsky" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_test( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// legacy section, no longer supported;
|
||||||
|
skip_until( Input, "endtest" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_time( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// current scenario time
|
||||||
|
cParser timeparser( Input.getToken<std::string>() );
|
||||||
|
timeparser.getTokens( 2, false, ":" );
|
||||||
|
auto &time = simulation::Time.data();
|
||||||
|
timeparser
|
||||||
|
>> time.wHour
|
||||||
|
>> time.wMinute;
|
||||||
|
|
||||||
|
// remaining sunrise and sunset parameters are no longer used, as they're now calculated dynamically
|
||||||
|
// anything else left in the section has no defined meaning
|
||||||
|
skip_until( Input, "endtime" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
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 " + std::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 ) {
|
||||||
|
|
||||||
|
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 " + std::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
|
||||||
|
TTrack *
|
||||||
|
state_manager::deserialize_path( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
|
// TODO: refactor track and wrapper classes and their de/serialization. do offset and rotation after deserialization is done
|
||||||
|
auto *track = new TTrack( Nodedata );
|
||||||
|
Math3D::vector3 offset = (
|
||||||
|
Scratchpad.location.offset.empty() ?
|
||||||
|
Math3D::vector3() :
|
||||||
|
Math3D::vector3(
|
||||||
|
Scratchpad.location.offset.top().x,
|
||||||
|
Scratchpad.location.offset.top().y,
|
||||||
|
Scratchpad.location.offset.top().z ) );
|
||||||
|
track->Load( &Input, offset );
|
||||||
|
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = (
|
||||||
|
Scratchpad.location.offset.empty() ?
|
||||||
|
glm::dvec3() :
|
||||||
|
Scratchpad.location.offset.top() );
|
||||||
|
traction->Load( &Input, offset );
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
|
||||||
|
auto *memorycell = new TMemCell( Nodedata );
|
||||||
|
memorycell->Load( &Input );
|
||||||
|
// adjust location
|
||||||
|
memorycell->location( transform( memorycell->location(), Scratchpad ) );
|
||||||
|
|
||||||
|
return memorycell;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEventLauncher *
|
||||||
|
state_manager::deserialize_eventlauncher( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
|
glm::dvec3 location;
|
||||||
|
Input.getTokens( 3 );
|
||||||
|
Input
|
||||||
|
>> location.x
|
||||||
|
>> location.y
|
||||||
|
>> location.z;
|
||||||
|
|
||||||
|
auto *eventlauncher = new TEventLauncher( Nodedata );
|
||||||
|
eventlauncher->Load( &Input );
|
||||||
|
eventlauncher->location( transform( location, Scratchpad ) );
|
||||||
|
|
||||||
|
return eventlauncher;
|
||||||
|
}
|
||||||
|
|
||||||
|
TAnimModel *
|
||||||
|
state_manager::deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata ) {
|
||||||
|
|
||||||
|
glm::dvec3 location;
|
||||||
|
glm::vec3 rotation;
|
||||||
|
Input.getTokens( 4 );
|
||||||
|
Input
|
||||||
|
>> location.x
|
||||||
|
>> location.y
|
||||||
|
>> location.z
|
||||||
|
>> rotation.y;
|
||||||
|
|
||||||
|
auto *instance = new TAnimModel( Nodedata );
|
||||||
|
instance->RaAnglesSet( Scratchpad.location.rotation + rotation ); // dostosowanie do pochylania linii
|
||||||
|
|
||||||
|
if( false == instance->Load( &Input, false ) ) {
|
||||||
|
// model nie wczytał się - ignorowanie node
|
||||||
|
SafeDelete( instance );
|
||||||
|
}
|
||||||
|
instance->location( transform( location, Scratchpad ) );
|
||||||
|
|
||||||
|
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 couplingdata = (
|
||||||
|
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 couplingdatawithparams = couplingdata.find( '.' );
|
||||||
|
auto coupling = (
|
||||||
|
couplingdatawithparams != std::string::npos ?
|
||||||
|
std::atoi( couplingdata.substr( 0, couplingdatawithparams ).c_str() ) :
|
||||||
|
std::atoi( couplingdata.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 = coupling::faux;
|
||||||
|
}
|
||||||
|
auto const params = (
|
||||||
|
couplingdatawithparams != std::string::npos ?
|
||||||
|
couplingdata.substr( couplingdatawithparams + 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
sound *
|
||||||
|
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 = sound_man->create_text_sound(soundname);
|
||||||
|
sound->position((glm::vec3)location).dist(Nodedata.range_max);
|
||||||
|
skip_until( Input, "endsound" );
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skips content of stream until specified token
|
||||||
|
void
|
||||||
|
state_manager::skip_until( cParser &Input, std::string const &Token ) {
|
||||||
|
|
||||||
|
std::string token { Input.getToken<std::string>() };
|
||||||
|
while( ( false == token.empty() )
|
||||||
|
&& ( token != Token ) ) {
|
||||||
|
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// transforms provided location by specifed rotation and offset
|
||||||
|
glm::dvec3
|
||||||
|
state_manager::transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad ) {
|
||||||
|
|
||||||
|
if( Scratchpad.location.rotation != glm::vec3( 0, 0, 0 ) ) {
|
||||||
|
auto const rotation = glm::radians( Scratchpad.location.rotation );
|
||||||
|
Location = glm::rotateY<double>( Location, rotation.y ); // Ra 2014-11: uwzględnienie rotacji
|
||||||
|
}
|
||||||
|
if( false == Scratchpad.location.offset.empty() ) {
|
||||||
|
Location += Scratchpad.location.offset.top();
|
||||||
|
}
|
||||||
|
return Location;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // simulation
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
92
simulation.h
Normal file
92
simulation.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
#include "scene.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "MemCell.h"
|
||||||
|
#include "EvLaunch.h"
|
||||||
|
#include "Track.h"
|
||||||
|
#include "Traction.h"
|
||||||
|
#include "TractionPower.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "AnimModel.h"
|
||||||
|
#include "DynObj.h"
|
||||||
|
#include "Driver.h"
|
||||||
|
#include "lightarray.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "lua.h"
|
||||||
|
|
||||||
|
namespace simulation {
|
||||||
|
|
||||||
|
class state_manager {
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// methods
|
||||||
|
// restores class data from provided stream
|
||||||
|
void deserialize( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_camera( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_config( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_description( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_event( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_lua( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_firstinit( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_light( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_node( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_origin( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_endorigin( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_rotate( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_sky( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_test( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_time( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
void deserialize_trainset( cParser &Input, scene::scratch_data &Scratchpad );
|
||||||
|
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 );
|
||||||
|
TEventLauncher * deserialize_eventlauncher( 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 );
|
||||||
|
sound * 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
|
||||||
|
glm::dvec3 transform( glm::dvec3 Location, scene::scratch_data const &Scratchpad );
|
||||||
|
};
|
||||||
|
|
||||||
|
extern state_manager State;
|
||||||
|
extern event_manager Events;
|
||||||
|
extern memory_table Memory;
|
||||||
|
extern path_table Paths;
|
||||||
|
extern traction_table Traction;
|
||||||
|
extern powergridsource_table Powergrid;
|
||||||
|
extern instance_table Instances;
|
||||||
|
extern vehicle_table Vehicles;
|
||||||
|
extern light_array Lights;
|
||||||
|
extern lua Lua;
|
||||||
|
|
||||||
|
extern scene::basic_region *Region;
|
||||||
|
|
||||||
|
} // simulation
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
@@ -348,6 +348,13 @@ sound& sound::position(glm::vec3 p)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 sound::location()
|
||||||
|
{
|
||||||
|
if (mode == global)
|
||||||
|
throw std::runtime_error("sound: bad state, no position");
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
sound& sound::position(Math3D::vector3 const &pos)
|
sound& sound::position(Math3D::vector3 const &pos)
|
||||||
{
|
{
|
||||||
position((glm::vec3)glm::make_vec3(&pos.x));
|
position((glm::vec3)glm::make_vec3(&pos.x));
|
||||||
|
|||||||
2
sound.h
2
sound.h
@@ -13,6 +13,7 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "Names.h"
|
||||||
|
|
||||||
class load_error : public std::runtime_error
|
class load_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
@@ -70,6 +71,7 @@ public:
|
|||||||
|
|
||||||
virtual ~sound();
|
virtual ~sound();
|
||||||
|
|
||||||
|
glm::vec3 location(); //get position
|
||||||
virtual bool is_playing() = 0;
|
virtual bool is_playing() = 0;
|
||||||
|
|
||||||
virtual void play() = 0;
|
virtual void play() = 0;
|
||||||
|
|||||||
1
stdafx.h
1
stdafx.h
@@ -49,6 +49,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <tuple>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ static std::unordered_map<std::string, std::string> m_cabcontrols = {
|
|||||||
{ "pantalloff_sw:", "all pantographs" },
|
{ "pantalloff_sw:", "all pantographs" },
|
||||||
{ "pantselected_sw:", "selected pantograph" },
|
{ "pantselected_sw:", "selected pantograph" },
|
||||||
{ "pantselectedoff_sw:", "selected pantograph" },
|
{ "pantselectedoff_sw:", "selected pantograph" },
|
||||||
|
{ "pantcompressor_sw:", "pantograph compressor" },
|
||||||
|
{ "pantcompressorvalve_sw:", "pantograph 3 way valve" },
|
||||||
{ "trainheating_sw:", "heating" },
|
{ "trainheating_sw:", "heating" },
|
||||||
{ "signalling_sw:", "braking indicator" },
|
{ "signalling_sw:", "braking indicator" },
|
||||||
{ "door_signalling_sw:", "door locking" },
|
{ "door_signalling_sw:", "door locking" },
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERSION_MAJOR 17
|
#define VERSION_MAJOR 17
|
||||||
#define VERSION_MINOR 914
|
#define VERSION_MINOR 1027
|
||||||
#define VERSION_REVISION 0
|
#define VERSION_REVISION 0
|
||||||
|
|||||||
33
vertex.cpp
Normal file
33
vertex.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "vertex.h"
|
||||||
|
|
||||||
|
template <>
|
||||||
|
world_vertex &
|
||||||
|
world_vertex::operator+=( world_vertex const &Right ) {
|
||||||
|
|
||||||
|
position += Right.position;
|
||||||
|
normal += Right.normal;
|
||||||
|
texture += Right.texture;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
world_vertex &
|
||||||
|
world_vertex::operator*=( world_vertex const &Right ) {
|
||||||
|
|
||||||
|
position *= Right.position;
|
||||||
|
normal *= Right.normal;
|
||||||
|
texture *= Right.texture;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
87
vertex.h
Normal file
87
vertex.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include "usefull.h"
|
||||||
|
|
||||||
|
// geometry vertex with double precision position
|
||||||
|
struct world_vertex {
|
||||||
|
|
||||||
|
// members
|
||||||
|
glm::dvec3 position;
|
||||||
|
glm::vec3 normal;
|
||||||
|
glm::vec2 texture;
|
||||||
|
|
||||||
|
// overloads
|
||||||
|
// operator+
|
||||||
|
template <typename Scalar_>
|
||||||
|
world_vertex &
|
||||||
|
operator+=( Scalar_ const &Right ) {
|
||||||
|
position += Right;
|
||||||
|
normal += Right;
|
||||||
|
texture += Right;
|
||||||
|
return *this; }
|
||||||
|
template <typename Scalar_>
|
||||||
|
friend
|
||||||
|
world_vertex
|
||||||
|
operator+( world_vertex Left, Scalar_ const &Right ) {
|
||||||
|
Left += Right;
|
||||||
|
return Left; }
|
||||||
|
// operator*
|
||||||
|
template <typename Scalar_>
|
||||||
|
world_vertex &
|
||||||
|
operator*=( Scalar_ const &Right ) {
|
||||||
|
position *= Right;
|
||||||
|
normal *= Right;
|
||||||
|
texture *= Right;
|
||||||
|
return *this; }
|
||||||
|
template <typename Type_>
|
||||||
|
friend
|
||||||
|
world_vertex
|
||||||
|
operator*( world_vertex Left, Type_ const &Right ) {
|
||||||
|
Left *= Right;
|
||||||
|
return Left; }
|
||||||
|
// methods
|
||||||
|
// wyliczenie współrzędnych i mapowania punktu na środku odcinka v1<->v2
|
||||||
|
void
|
||||||
|
set_half( world_vertex const &Vertex1, world_vertex const &Vertex2 ) {
|
||||||
|
*this =
|
||||||
|
interpolate(
|
||||||
|
Vertex1,
|
||||||
|
Vertex2,
|
||||||
|
0.5 ); }
|
||||||
|
// wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
|
||||||
|
void
|
||||||
|
set_from_x( world_vertex const &Vertex1, world_vertex const &Vertex2, double const X ) {
|
||||||
|
*this =
|
||||||
|
interpolate(
|
||||||
|
Vertex1,
|
||||||
|
Vertex2,
|
||||||
|
( X - Vertex1.position.x ) / ( Vertex2.position.x - Vertex1.position.x ) ); }
|
||||||
|
// wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
|
||||||
|
void
|
||||||
|
set_from_z( world_vertex const &Vertex1, world_vertex const &Vertex2, double const Z ) {
|
||||||
|
*this =
|
||||||
|
interpolate(
|
||||||
|
Vertex1,
|
||||||
|
Vertex2,
|
||||||
|
( Z - Vertex1.position.z ) / ( Vertex2.position.z - Vertex1.position.z ) ); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
world_vertex &
|
||||||
|
world_vertex::operator+=( world_vertex const &Right );
|
||||||
|
|
||||||
|
template <>
|
||||||
|
world_vertex &
|
||||||
|
world_vertex::operator*=( world_vertex const &Right );
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
@@ -63,7 +63,7 @@ LRESULT APIENTRY WndProc( HWND hWnd, // handle for this window
|
|||||||
// obsługa danych przesłanych przez program sterujący
|
// obsługa danych przesłanych przez program sterujący
|
||||||
pDane = (PCOPYDATASTRUCT)lParam;
|
pDane = (PCOPYDATASTRUCT)lParam;
|
||||||
if( pDane->dwData == MAKE_ID4('E', 'U', '0', '7')) // sygnatura danych
|
if( pDane->dwData == MAKE_ID4('E', 'U', '0', '7')) // sygnatura danych
|
||||||
World.OnCommandGet( (DaneRozkaz *)( pDane->lpData ) );
|
World.OnCommandGet( ( multiplayer::DaneRozkaz *)( pDane->lpData ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#else
|
#else
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#define WORD uint16_t
|
#define WORD uint16_t
|
||||||
|
#define UINT uint32_t
|
||||||
|
#define WPARAM uint64_t
|
||||||
|
#define LPARAM uint64_t
|
||||||
#define DWORD uint32_t
|
#define DWORD uint32_t
|
||||||
#define LONG int32_t
|
#define LONG int32_t
|
||||||
#define BYTE uint8_t
|
#define BYTE uint8_t
|
||||||
|
|||||||
Reference in New Issue
Block a user