mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 08:39:18 +02:00
partial initial refactoring: events, memcells, tracks, models, traction; NOTE: debug mode broken, investigate
This commit is contained in:
@@ -406,23 +406,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()
|
||||||
|
|||||||
87
AnimModel.h
87
AnimModel.h
@@ -21,13 +21,13 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
const int iMaxNumLights = 8;
|
const int iMaxNumLights = 8;
|
||||||
|
|
||||||
// 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
|
||||||
@@ -118,55 +118,66 @@ 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;
|
||||||
|
|
||||||
private:
|
public:
|
||||||
TAnimContainer *pRoot; // pojemniki sterujące, tylko dla aniomowanych submodeli
|
// constructors
|
||||||
TModel3d *pModel;
|
TAnimModel( scene::node_data const &Nodedata );
|
||||||
double fBlinkTimer;
|
|
||||||
int iNumLights;
|
|
||||||
TSubModel *LightsOn[iMaxNumLights]; // Ra: te wskaźniki powinny być w ramach TModel3d
|
|
||||||
TSubModel *LightsOff[iMaxNumLights];
|
|
||||||
vector3 vAngle; // bazowe obroty egzemplarza względem osi
|
|
||||||
material_data m_materialdata;
|
|
||||||
|
|
||||||
std::string asText; // tekst dla wyświetlacza znakowego
|
|
||||||
TAnimAdvanced *pAdvanced { nullptr };
|
|
||||||
void Advanced();
|
|
||||||
TLightState lsLights[iMaxNumLights];
|
|
||||||
float fDark; // 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
|
|
||||||
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();
|
||||||
|
// destructor
|
||||||
~TAnimModel();
|
~TAnimModel();
|
||||||
|
// methods
|
||||||
|
static void AnimUpdate( double dt );
|
||||||
bool Init(TModel3d *pNewModel);
|
bool Init(TModel3d *pNewModel);
|
||||||
bool Init(std::string const &asName, std::string const &asReplacableTexture);
|
bool Init(std::string const &asName, std::string const &asReplacableTexture);
|
||||||
bool Load(cParser *parser, bool ter = false);
|
bool Load(cParser *parser, bool ter = false);
|
||||||
TAnimContainer * AddContainer(std::string const &Name);
|
TAnimContainer * AddContainer(std::string const &Name);
|
||||||
TAnimContainer * GetContainer(std::string const &Name = "");
|
TAnimContainer * GetContainer(std::string const &Name = "");
|
||||||
int Flags();
|
void RaAnglesSet( glm::vec3 Angles ) {
|
||||||
void RaAnglesSet(double a, double b, double c)
|
vAngle.x = Angles.x;
|
||||||
{
|
vAngle.y = Angles.y;
|
||||||
vAngle.x = a;
|
vAngle.z = Angles.z; };
|
||||||
vAngle.y = b;
|
void LightSet( int n, float v );
|
||||||
vAngle.z = c;
|
void AnimationVND( void *pData, double a, double b, double c, double d );
|
||||||
};
|
|
||||||
bool TerrainLoaded();
|
bool TerrainLoaded();
|
||||||
int TerrainCount();
|
int TerrainCount();
|
||||||
TSubModel * TerrainSquare(int n);
|
TSubModel * TerrainSquare(int n);
|
||||||
void AnimationVND(void *pData, double a, double b, double c, double d);
|
int Flags();
|
||||||
void LightSet(int n, float v);
|
inline
|
||||||
static void AnimUpdate(double dt);
|
material_data const *
|
||||||
|
Material() const {
|
||||||
|
return &m_materialdata; }
|
||||||
|
// members
|
||||||
|
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
|
||||||
|
|
||||||
|
private:
|
||||||
|
// methods
|
||||||
|
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
|
||||||
|
void RaAnimate( unsigned int const Framestamp ); // przeliczenie animacji egzemplarza
|
||||||
|
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 *LightsOff[ iMaxNumLights ];
|
||||||
|
vector3 vAngle; // bazowe obroty egzemplarza względem osi
|
||||||
|
material_data m_materialdata;
|
||||||
|
|
||||||
|
std::string asText; // tekst dla wyświetlacza znakowego
|
||||||
|
TAnimAdvanced *pAdvanced { nullptr };
|
||||||
|
TLightState lsLights[ iMaxNumLights ];
|
||||||
|
float fDark { 0.25f }; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)
|
||||||
|
float 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
|
||||||
|
};
|
||||||
|
|
||||||
|
class instance_manager : public basic_table<TAnimModel> {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2957,12 +2957,6 @@ 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
|
||||||
|
|||||||
908
Event.cpp
908
Event.cpp
@@ -14,7 +14,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Event.h"
|
#include "event.h"
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "Usefull.h"
|
#include "Usefull.h"
|
||||||
@@ -23,6 +24,10 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "MemCell.h"
|
#include "MemCell.h"
|
||||||
#include "Ground.h"
|
#include "Ground.h"
|
||||||
#include "McZapkie\mctools.h"
|
#include "McZapkie\mctools.h"
|
||||||
|
#include "animmodel.h"
|
||||||
|
#include "dynobj.h"
|
||||||
|
#include "driver.h"
|
||||||
|
#include "tractionpower.h"
|
||||||
|
|
||||||
TEvent::TEvent( std::string const &m ) :
|
TEvent::TEvent( std::string const &m ) :
|
||||||
asNodeName( m )
|
asNodeName( m )
|
||||||
@@ -36,8 +41,8 @@ TEvent::TEvent( std::string const &m ) :
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEvent::~TEvent()
|
TEvent::~TEvent() {
|
||||||
{
|
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{ // sprzątanie
|
{ // sprzątanie
|
||||||
case tp_Multiple:
|
case tp_Multiple:
|
||||||
@@ -56,14 +61,17 @@ TEvent::~TEvent()
|
|||||||
// SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa jest zamieniana na wskaźnik do
|
// SafeDeleteArray(Params[9].asText); //nie usuwać - nazwa jest zamieniana na wskaźnik do
|
||||||
// submodelu
|
// submodelu
|
||||||
if (Params[0].asInt == 4) // jeśli z pliku VMD
|
if (Params[0].asInt == 4) // jeśli z pliku VMD
|
||||||
delete[] Params[8].asPointer; // zwolnić obszar
|
SafeDeleteArray( Params[8].asPointer ); // zwolnić obszar
|
||||||
case tp_GetValues: // nic
|
case tp_GetValues: // nic
|
||||||
break;
|
break;
|
||||||
case tp_PutValues: // params[0].astext stores the token
|
case tp_PutValues: // params[0].astext stores the token
|
||||||
SafeDeleteArray( Params[ 0 ].asText );
|
SafeDeleteArray( Params[ 0 ].asText );
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
evJoined = NULL; // nie usuwać podczepionych tutaj
|
evJoined = nullptr; // nie usuwać podczepionych tutaj
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void TEvent::Init(){
|
void TEvent::Init(){
|
||||||
@@ -138,7 +146,7 @@ void TEvent::Conditions(cParser *parser, std::string s)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void TEvent::Load(cParser *parser, vector3 *org)
|
void TEvent::Load(cParser *parser, Math3D::vector3 const &org)
|
||||||
{
|
{
|
||||||
std::string token;
|
std::string token;
|
||||||
|
|
||||||
@@ -294,12 +302,12 @@ void TEvent::Load(cParser *parser, vector3 *org)
|
|||||||
parser->getTokens(3);
|
parser->getTokens(3);
|
||||||
*parser >> Params[3].asdouble >> Params[4].asdouble >> Params[5].asdouble; // położenie
|
*parser >> Params[3].asdouble >> Params[4].asdouble >> Params[5].asdouble; // położenie
|
||||||
// X,Y,Z
|
// X,Y,Z
|
||||||
if (org)
|
if ( !(org == Math3D::vector3()) )
|
||||||
{ // przesunięcie
|
{ // przesunięcie
|
||||||
// tmp->pCenter.RotateY(aRotate.y/180.0*M_PI); //Ra 2014-11: uwzględnienie rotacji
|
// tmp->pCenter.RotateY(aRotate.y/180.0*M_PI); //Ra 2014-11: uwzględnienie rotacji
|
||||||
Params[3].asdouble += org->x; // współrzędne w scenerii
|
Params[3].asdouble += org.x; // współrzędne w scenerii
|
||||||
Params[4].asdouble += org->y;
|
Params[4].asdouble += org.y;
|
||||||
Params[5].asdouble += org->z;
|
Params[5].asdouble += org.z;
|
||||||
}
|
}
|
||||||
// Params[12].asInt=0;
|
// Params[12].asInt=0;
|
||||||
parser->getTokens(1, false); // komendy 'case sensitive'
|
parser->getTokens(1, false); // komendy 'case sensitive'
|
||||||
@@ -679,16 +687,16 @@ double TEvent::ValueGet(int n)
|
|||||||
return 0.0; // inne eventy się nie liczą
|
return 0.0; // inne eventy się nie liczą
|
||||||
};
|
};
|
||||||
|
|
||||||
vector3 TEvent::PositionGet() const
|
glm::dvec3 TEvent::PositionGet() const
|
||||||
{ // pobranie współrzędnych eventu
|
{ // pobranie współrzędnych eventu
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{ //
|
{ //
|
||||||
case tp_GetValues:
|
case tp_GetValues:
|
||||||
return Params[9].asMemCell->Position(); // współrzędne podłączonej komórki pamięci
|
return Params[9].asMemCell->location(); // współrzędne podłączonej komórki pamięci
|
||||||
case tp_PutValues:
|
case tp_PutValues:
|
||||||
return vector3(Params[3].asdouble, Params[4].asdouble, Params[5].asdouble);
|
return glm::dvec3(Params[3].asdouble, Params[4].asdouble, Params[5].asdouble);
|
||||||
}
|
}
|
||||||
return vector3(0, 0, 0); // inne eventy się nie liczą
|
return glm::dvec3(0, 0, 0); // inne eventy się nie liczą
|
||||||
};
|
};
|
||||||
|
|
||||||
bool TEvent::StopCommand()
|
bool TEvent::StopCommand()
|
||||||
@@ -714,3 +722,875 @@ void TEvent::Append(TEvent *e)
|
|||||||
e->bEnabled = true; // ten doczepiony może być tylko kolejkowany
|
e->bEnabled = true; // ten doczepiony może być tylko kolejkowany
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
event_manager::~event_manager() {
|
||||||
|
|
||||||
|
for( auto *event : m_events ) {
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided event to the collection. returns: true on success
|
||||||
|
// TODO: return handle instead of pointer
|
||||||
|
bool
|
||||||
|
event_manager::insert( TEvent *Event ) {
|
||||||
|
|
||||||
|
if( Event->Type == tp_Unknown ) { return false; }
|
||||||
|
|
||||||
|
// najpierw sprawdzamy, czy nie ma, a potem dopisujemy
|
||||||
|
auto lookup = m_eventmap.find( Event->asName );
|
||||||
|
if( lookup != m_eventmap.end() ) {
|
||||||
|
// duplicate of already existing event
|
||||||
|
auto const size = Event->asName.size();
|
||||||
|
// zawsze jeden znak co najmniej jest
|
||||||
|
if( Event->asName[ 0 ] == '#' ) {
|
||||||
|
// utylizacja duplikatu z krzyżykiem
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// tymczasowo wyjątki:
|
||||||
|
else if( ( size > 8 )
|
||||||
|
&& ( Event->asName.substr( 0, 9 ) == "lineinfo:" ) ) {
|
||||||
|
// tymczasowa utylizacja duplikatów W5
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if( ( size > 8 )
|
||||||
|
&& ( Event->asName.substr( size - 8 ) == "_warning" ) ) {
|
||||||
|
// tymczasowa utylizacja duplikatu z trąbieniem
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if( ( size > 4 )
|
||||||
|
&& ( Event->asName.substr( size - 4 ) == "_shp" ) ) {
|
||||||
|
// nie podlegają logowaniu
|
||||||
|
// tymczasowa utylizacja duplikatu SHP
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *duplicate = m_events[ lookup->second ];
|
||||||
|
if( Global::bJoinEvents ) {
|
||||||
|
// doczepka (taki wirtualny multiple bez warunków)
|
||||||
|
duplicate->Append( Event );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// NOTE: somewhat convoluted way to deal with 'replacing' events without leaving dangling pointers
|
||||||
|
// can be cleaned up if pointers to events were replaced with handles
|
||||||
|
ErrorLog( "Bad event: encountered duplicated event, \"" + Event->asName + "\"" );
|
||||||
|
duplicate->Append( Event ); // doczepka (taki wirtualny multiple bez warunków)
|
||||||
|
// BUG: source of memory leak.
|
||||||
|
// erasing original type of event prevents it from proper resource de-allocation on exit
|
||||||
|
// TODO: mark ignored event with separate flag or ideally refactor the whole thing
|
||||||
|
duplicate->Type = tp_Ignored; // dezaktywacja pierwotnego - taka proteza na wsteczną zgodność
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_events.emplace_back( Event );
|
||||||
|
if( lookup == m_eventmap.end() ) {
|
||||||
|
// if it's first event with such name, it's potential candidate for the execution queue
|
||||||
|
m_eventmap.emplace( Event->asName, m_events.size() - 1 );
|
||||||
|
if( ( Event->Type != tp_Ignored )
|
||||||
|
&& ( Event->asName.find( "onstart" ) != std::string::npos ) ) {
|
||||||
|
// event uruchamiany automatycznie po starcie
|
||||||
|
AddToQuery( Event, nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, returns pointer to specified event, or null
|
||||||
|
TEvent *
|
||||||
|
event_manager::FindEvent( std::string const &Name ) {
|
||||||
|
|
||||||
|
if( Name.empty() ) { return nullptr; }
|
||||||
|
|
||||||
|
auto const lookup = m_eventmap.find( Name );
|
||||||
|
return (
|
||||||
|
lookup != m_eventmap.end() ?
|
||||||
|
m_events[ lookup->second ] :
|
||||||
|
nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, inserts specified event in the event query
|
||||||
|
bool
|
||||||
|
event_manager::AddToQuery( TEvent *Event, TDynamicObject *Owner ) {
|
||||||
|
|
||||||
|
if( Event->bEnabled ) {
|
||||||
|
// jeśli może być dodany do kolejki (nie używany w skanowaniu)
|
||||||
|
if( !Event->iQueued ) // jeśli nie dodany jeszcze do kolejki
|
||||||
|
{ // kolejka eventów jest posortowana względem (fStartTime)
|
||||||
|
Event->Activator = Owner;
|
||||||
|
if( ( Event->Type == tp_AddValues )
|
||||||
|
&& ( Event->fDelay == 0.0 ) ) {
|
||||||
|
// eventy AddValues trzeba wykonywać natychmiastowo, inaczej kolejka może zgubić jakieś dodawanie
|
||||||
|
// Ra: kopiowanie wykonania tu jest bez sensu, lepiej by było wydzielić funkcję
|
||||||
|
// wykonującą eventy i ją wywołać
|
||||||
|
if( EventConditon( Event ) ) { // teraz mogą być warunki do tych eventów
|
||||||
|
Event->Params[ 5 ].asMemCell->UpdateValues(
|
||||||
|
Event->Params[ 0 ].asText, Event->Params[ 1 ].asdouble,
|
||||||
|
Event->Params[ 2 ].asdouble, Event->iFlags );
|
||||||
|
if( Event->Params[ 6 ].asTrack ) { // McZapkie-100302 - updatevalues oprocz zmiany wartosci robi putcommand dla
|
||||||
|
// wszystkich 'dynamic' na danym torze
|
||||||
|
for( auto dynamic : Event->Params[ 6 ].asTrack->Dynamics ) {
|
||||||
|
Event->Params[ 5 ].asMemCell->PutCommand(
|
||||||
|
dynamic->Mechanik,
|
||||||
|
&Event->Params[ 4 ].nGroundNode->pCenter );
|
||||||
|
}
|
||||||
|
//if (DebugModeFlag)
|
||||||
|
WriteLog(
|
||||||
|
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues & Track command ( "
|
||||||
|
+ std::string( Event->Params[ 0 ].asText ) + " "
|
||||||
|
+ std::to_string( Event->Params[ 1 ].asdouble ) + " "
|
||||||
|
+ std::to_string( Event->Params[ 2 ].asdouble ) + " )" );
|
||||||
|
}
|
||||||
|
//else if (DebugModeFlag)
|
||||||
|
WriteLog(
|
||||||
|
"EVENT EXECUTED" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": AddValues ( "
|
||||||
|
+ std::string( Event->Params[ 0 ].asText ) + " "
|
||||||
|
+ std::to_string( Event->Params[ 1 ].asdouble ) + " "
|
||||||
|
+ std::to_string( Event->Params[ 2 ].asdouble ) + " )" );
|
||||||
|
}
|
||||||
|
// jeśli jest kolejny o takiej samej nazwie, to idzie do kolejki (and if there's no joint event it'll be set to null and processing will end here)
|
||||||
|
do {
|
||||||
|
Event = Event->evJoined;
|
||||||
|
// NOTE: we could've received a new event from joint event above, so we need to check conditions just in case and discard the bad events
|
||||||
|
// TODO: refactor this arrangement, it's hardly optimal
|
||||||
|
} while( ( Event != nullptr )
|
||||||
|
&& ( ( false == Event->bEnabled )
|
||||||
|
|| ( Event->iQueued > 0 ) ) );
|
||||||
|
}
|
||||||
|
if( Event != nullptr ) {
|
||||||
|
// standardowe dodanie do kolejki
|
||||||
|
++Event->iQueued; // zabezpieczenie przed podwójnym dodaniem do kolejki
|
||||||
|
WriteLog( "EVENT ADDED TO QUEUE" + ( Owner ? ( " by " + Owner->asName ) : "" ) + ": " + Event->asName );
|
||||||
|
Event->fStartTime = std::abs( Event->fDelay ) + Timer::GetTime(); // czas od uruchomienia scenerii
|
||||||
|
if( Event->fRandomDelay > 0.0 ) {
|
||||||
|
// doliczenie losowego czasu opóźnienia
|
||||||
|
Event->fStartTime += Event->fRandomDelay * Random( 10000 ) * 0.0001;
|
||||||
|
}
|
||||||
|
if( QueryRootEvent != nullptr ) {
|
||||||
|
TEvent::AddToQuery( Event, QueryRootEvent );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QueryRootEvent = Event;
|
||||||
|
QueryRootEvent->evNext = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, executes queued events
|
||||||
|
bool
|
||||||
|
event_manager::CheckQuery() {
|
||||||
|
|
||||||
|
TLocation loc;
|
||||||
|
int i;
|
||||||
|
while( ( QueryRootEvent != nullptr )
|
||||||
|
&& ( QueryRootEvent->fStartTime < Timer::GetTime() ) )
|
||||||
|
{ // eventy są posortowana wg czasu wykonania
|
||||||
|
m_workevent = QueryRootEvent; // wyjęcie eventu z kolejki
|
||||||
|
if (QueryRootEvent->evJoined) // jeśli jest kolejny o takiej samej nazwie
|
||||||
|
{ // to teraz on będzie następny do wykonania
|
||||||
|
QueryRootEvent = QueryRootEvent->evJoined; // następny będzie ten doczepiony
|
||||||
|
QueryRootEvent->evNext = m_workevent->evNext; // pamiętając o następnym z kolejki
|
||||||
|
QueryRootEvent->fStartTime = m_workevent->fStartTime; // czas musi być ten sam, bo nie jest aktualizowany
|
||||||
|
QueryRootEvent->Activator = m_workevent->Activator; // pojazd aktywujący
|
||||||
|
QueryRootEvent->iQueued = 1;
|
||||||
|
// w sumie można by go dodać normalnie do kolejki, ale trzeba te połączone posortować wg czasu wykonania
|
||||||
|
}
|
||||||
|
else // a jak nazwa jest unikalna, to kolejka idzie dalej
|
||||||
|
QueryRootEvent = QueryRootEvent->evNext; // NULL w skrajnym przypadku
|
||||||
|
if (m_workevent->bEnabled)
|
||||||
|
{ // w zasadzie te wyłączone są skanowane i nie powinny się nigdy w kolejce znaleźć
|
||||||
|
--m_workevent->iQueued; // teraz moze być ponownie dodany do kolejki
|
||||||
|
WriteLog( "EVENT LAUNCHED" + ( m_workevent->Activator ? ( " by " + m_workevent->Activator->asName ) : "" ) + ": " + m_workevent->asName );
|
||||||
|
switch (m_workevent->Type)
|
||||||
|
{
|
||||||
|
case tp_CopyValues: // skopiowanie wartości z innej komórki
|
||||||
|
m_workevent->Params[5].asMemCell->UpdateValues(
|
||||||
|
m_workevent->Params[9].asMemCell->Text(),
|
||||||
|
m_workevent->Params[9].asMemCell->Value1(),
|
||||||
|
m_workevent->Params[9].asMemCell->Value2(),
|
||||||
|
m_workevent->iFlags // flagi określają, co ma być skopiowane
|
||||||
|
);
|
||||||
|
// break; //żeby się wysłało do torów i nie było potrzeby na AddValues * 0 0
|
||||||
|
case tp_AddValues: // różni się jedną flagą od UpdateValues
|
||||||
|
case tp_UpdateValues:
|
||||||
|
if (EventConditon(m_workevent))
|
||||||
|
{ // teraz mogą być warunki do tych eventów
|
||||||
|
if (m_workevent->Type != tp_CopyValues) // dla CopyValues zrobiło się wcześniej
|
||||||
|
m_workevent->Params[5].asMemCell->UpdateValues(
|
||||||
|
m_workevent->Params[0].asText,
|
||||||
|
m_workevent->Params[1].asdouble,
|
||||||
|
m_workevent->Params[2].asdouble,
|
||||||
|
m_workevent->iFlags);
|
||||||
|
if (m_workevent->Params[6].asTrack)
|
||||||
|
{ // McZapkie-100302 - updatevalues oprocz zmiany wartosci robi putcommand dla
|
||||||
|
// wszystkich 'dynamic' na danym torze
|
||||||
|
for( auto dynamic : m_workevent->Params[ 6 ].asTrack->Dynamics ) {
|
||||||
|
m_workevent->Params[ 5 ].asMemCell->PutCommand(
|
||||||
|
dynamic->Mechanik,
|
||||||
|
&m_workevent->Params[ 4 ].nGroundNode->pCenter );
|
||||||
|
}
|
||||||
|
//if (DebugModeFlag)
|
||||||
|
WriteLog("Type: UpdateValues & Track command - [" +
|
||||||
|
m_workevent->Params[5].asMemCell->Text() + "] [" +
|
||||||
|
to_string( m_workevent->Params[ 5 ].asMemCell->Value1(), 2 ) + "] [" +
|
||||||
|
to_string( m_workevent->Params[ 5 ].asMemCell->Value2(), 2 ) + "]" );
|
||||||
|
}
|
||||||
|
else //if (DebugModeFlag)
|
||||||
|
WriteLog("Type: UpdateValues - [" +
|
||||||
|
m_workevent->Params[5].asMemCell->Text() + "] [" +
|
||||||
|
to_string( m_workevent->Params[ 5 ].asMemCell->Value1(), 2 ) + "] [" +
|
||||||
|
to_string( m_workevent->Params[ 5 ].asMemCell->Value2(), 2 ) + "]" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tp_GetValues: {
|
||||||
|
if( m_workevent->Activator ) {
|
||||||
|
/*
|
||||||
|
// TODO: re-enable when messaging module is in place
|
||||||
|
if( Global::iMultiplayer ) {
|
||||||
|
// potwierdzenie wykonania dla serwera (odczyt semafora już tak nie działa)
|
||||||
|
WyslijEvent( tmpEvent->asName, tmpEvent->Activator->GetName() );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
m_workevent->Params[ 9 ].asMemCell->PutCommand(
|
||||||
|
m_workevent->Activator->Mechanik,
|
||||||
|
&m_workevent->Params[ 8 ].nGroundNode->pCenter );
|
||||||
|
}
|
||||||
|
WriteLog( "Type: GetValues" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_PutValues: {
|
||||||
|
if (m_workevent->Activator) {
|
||||||
|
// zamiana, bo fizyka ma inaczej niż sceneria
|
||||||
|
loc.X = -m_workevent->Params[3].asdouble;
|
||||||
|
loc.Y = m_workevent->Params[5].asdouble;
|
||||||
|
loc.Z = m_workevent->Params[4].asdouble;
|
||||||
|
if( m_workevent->Activator->Mechanik ) {
|
||||||
|
// przekazanie rozkazu do AI
|
||||||
|
m_workevent->Activator->Mechanik->PutCommand(
|
||||||
|
m_workevent->Params[0].asText, m_workevent->Params[1].asdouble,
|
||||||
|
m_workevent->Params[2].asdouble, loc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// przekazanie do pojazdu
|
||||||
|
m_workevent->Activator->MoverParameters->PutCommand(
|
||||||
|
m_workevent->Params[0].asText, m_workevent->Params[1].asdouble,
|
||||||
|
m_workevent->Params[2].asdouble, loc);
|
||||||
|
}
|
||||||
|
WriteLog("Type: PutValues - [" +
|
||||||
|
std::string(m_workevent->Params[0].asText) + "] [" +
|
||||||
|
to_string( m_workevent->Params[ 1 ].asdouble, 2 ) + "] [" +
|
||||||
|
to_string( m_workevent->Params[ 2 ].asdouble, 2 ) + "]" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Lights:
|
||||||
|
if (m_workevent->Params[9].asModel)
|
||||||
|
for (i = 0; i < iMaxNumLights; i++)
|
||||||
|
if (m_workevent->Params[i].asdouble >= 0) //-1 zostawia bez zmiany
|
||||||
|
m_workevent->Params[9].asModel->LightSet(
|
||||||
|
i, m_workevent->Params[i].asdouble); // teraz też ułamek
|
||||||
|
break;
|
||||||
|
case tp_Visible:
|
||||||
|
if (m_workevent->Params[9].nGroundNode)
|
||||||
|
m_workevent->Params[9].nGroundNode->bVisible = (m_workevent->Params[i].asInt > 0);
|
||||||
|
break;
|
||||||
|
case tp_Velocity:
|
||||||
|
Error("Not implemented yet :(");
|
||||||
|
break;
|
||||||
|
case tp_Exit:
|
||||||
|
MessageBox(0, m_workevent->asNodeName.c_str(), " THE END ", MB_OK);
|
||||||
|
Global::iTextMode = -1; // wyłączenie takie samo jak sekwencja F10 -> Y
|
||||||
|
return false;
|
||||||
|
case tp_Sound:
|
||||||
|
switch (m_workevent->Params[0].asInt)
|
||||||
|
{ // trzy możliwe przypadki:
|
||||||
|
case 0:
|
||||||
|
m_workevent->Params[9].tsTextSound->Stop();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m_workevent->Params[9].tsTextSound->Play(
|
||||||
|
1, 0, true, m_workevent->Params[9].tsTextSound->vSoundPosition);
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
m_workevent->Params[9].tsTextSound->Play(
|
||||||
|
1, DSBPLAY_LOOPING, true, m_workevent->Params[9].tsTextSound->vSoundPosition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tp_Disable:
|
||||||
|
Error("Not implemented yet :(");
|
||||||
|
break;
|
||||||
|
case tp_Animation: // Marcin: dorobic translacje - Ra: dorobiłem ;-)
|
||||||
|
if (m_workevent->Params[0].asInt == 1)
|
||||||
|
m_workevent->Params[9].asAnimContainer->SetRotateAnim(
|
||||||
|
Math3D::vector3(m_workevent->Params[1].asdouble, m_workevent->Params[2].asdouble,
|
||||||
|
m_workevent->Params[3].asdouble),
|
||||||
|
m_workevent->Params[4].asdouble);
|
||||||
|
else if (m_workevent->Params[0].asInt == 2)
|
||||||
|
m_workevent->Params[9].asAnimContainer->SetTranslateAnim(
|
||||||
|
Math3D::vector3(m_workevent->Params[1].asdouble, m_workevent->Params[2].asdouble,
|
||||||
|
m_workevent->Params[3].asdouble),
|
||||||
|
m_workevent->Params[4].asdouble);
|
||||||
|
else if (m_workevent->Params[0].asInt == 4)
|
||||||
|
m_workevent->Params[9].asModel->AnimationVND(
|
||||||
|
m_workevent->Params[8].asPointer,
|
||||||
|
m_workevent->Params[1].asdouble, // tu mogą być dodatkowe parametry, np. od-do
|
||||||
|
m_workevent->Params[2].asdouble, m_workevent->Params[3].asdouble,
|
||||||
|
m_workevent->Params[4].asdouble);
|
||||||
|
break;
|
||||||
|
case tp_Switch: {
|
||||||
|
if( m_workevent->Params[ 9 ].asTrack ) {
|
||||||
|
m_workevent->Params[ 9 ].asTrack->Switch(
|
||||||
|
m_workevent->Params[ 0 ].asInt,
|
||||||
|
m_workevent->Params[ 1 ].asdouble,
|
||||||
|
m_workevent->Params[ 2 ].asdouble );
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// TODO: re-enable when messaging module is in place
|
||||||
|
if( Global::iMultiplayer ) {
|
||||||
|
// dajemy znać do serwera o przełożeniu
|
||||||
|
WyslijEvent( m_workevent->asName, "" ); // wysłanie nazwy eventu przełączajacego
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// Ra: bardziej by się przydała nazwa toru, ale nie ma do niej stąd dostępu
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_TrackVel:
|
||||||
|
if (m_workevent->Params[9].asTrack)
|
||||||
|
{ // prędkość na zwrotnicy może być ograniczona z góry we wpisie, większej się nie
|
||||||
|
// ustawi eventem
|
||||||
|
WriteLog("Type: TrackVel");
|
||||||
|
m_workevent->Params[9].asTrack->VelocitySet(m_workevent->Params[0].asdouble);
|
||||||
|
if (DebugModeFlag) // wyświetlana jest ta faktycznie ustawiona
|
||||||
|
WriteLog(" - velocity: ", m_workevent->Params[9].asTrack->VelocityGet());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tp_DynVel:
|
||||||
|
Error("Event \"DynVel\" is obsolete");
|
||||||
|
break;
|
||||||
|
case tp_Multiple: {
|
||||||
|
auto const bCondition = EventConditon(m_workevent);
|
||||||
|
if( ( bCondition )
|
||||||
|
|| ( m_workevent->iFlags & conditional_anyelse ) ) {
|
||||||
|
// warunek spelniony albo było użyte else
|
||||||
|
WriteLog("Type: Multi-event");
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
// dodawane do kolejki w kolejności zapisania
|
||||||
|
if( m_workevent->Params[ i ].asEvent ) {
|
||||||
|
if( bCondition != ( ( ( m_workevent->iFlags & ( conditional_else << i ) ) != 0 ) ) ) {
|
||||||
|
if( m_workevent->Params[ i ].asEvent != m_workevent )
|
||||||
|
AddToQuery( m_workevent->Params[ i ].asEvent, m_workevent->Activator ); // normalnie dodać
|
||||||
|
else {
|
||||||
|
// jeśli ma być rekurencja to musi mieć sensowny okres powtarzania
|
||||||
|
if( m_workevent->fDelay >= 5.0 ) {
|
||||||
|
AddToQuery( m_workevent, m_workevent->Activator );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// TODO: re-enable when messaging component is in place
|
||||||
|
if( Global::iMultiplayer ) {
|
||||||
|
// dajemy znać do serwera o wykonaniu
|
||||||
|
if( ( m_workevent->iFlags & conditional_anyelse ) == 0 ) {
|
||||||
|
// jednoznaczne tylko, gdy nie było else
|
||||||
|
if( m_workevent->Activator ) {
|
||||||
|
WyslijEvent( m_workevent->asName, m_workevent->Activator->GetName() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WyslijEvent( m_workevent->asName, "" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_WhoIs: {
|
||||||
|
// pobranie nazwy pociągu do komórki pamięci
|
||||||
|
if (m_workevent->iFlags & update_load) {
|
||||||
|
// jeśli pytanie o ładunek
|
||||||
|
if( m_workevent->iFlags & update_memadd ) {
|
||||||
|
// jeśli typ pojazdu
|
||||||
|
// TODO: define and recognize individual request types
|
||||||
|
auto const owner = (
|
||||||
|
( ( m_workevent->Activator->Mechanik != nullptr ) && ( m_workevent->Activator->Mechanik->Primary() ) ) ?
|
||||||
|
m_workevent->Activator->Mechanik :
|
||||||
|
m_workevent->Activator->ctOwner );
|
||||||
|
auto const consistbrakelevel = (
|
||||||
|
owner != nullptr ?
|
||||||
|
owner->fReady :
|
||||||
|
-1.0 );
|
||||||
|
auto const collisiondistance = (
|
||||||
|
owner != nullptr ?
|
||||||
|
owner->TrackBlock() :
|
||||||
|
-1.0 );
|
||||||
|
|
||||||
|
m_workevent->Params[ 9 ].asMemCell->UpdateValues(
|
||||||
|
m_workevent->Activator->MoverParameters->TypeName, // typ pojazdu
|
||||||
|
consistbrakelevel,
|
||||||
|
collisiondistance,
|
||||||
|
m_workevent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) );
|
||||||
|
|
||||||
|
WriteLog(
|
||||||
|
"Type: WhoIs (" + to_string( m_workevent->iFlags ) + ") - "
|
||||||
|
+ "[name: " + m_workevent->Activator->MoverParameters->TypeName + "], "
|
||||||
|
+ "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], "
|
||||||
|
+ "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// jeśli parametry ładunku
|
||||||
|
m_workevent->Params[ 9 ].asMemCell->UpdateValues(
|
||||||
|
m_workevent->Activator->MoverParameters->LoadType, // nazwa ładunku
|
||||||
|
m_workevent->Activator->MoverParameters->Load, // aktualna ilość
|
||||||
|
m_workevent->Activator->MoverParameters->MaxLoad, // maksymalna ilość
|
||||||
|
m_workevent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) );
|
||||||
|
|
||||||
|
WriteLog(
|
||||||
|
"Type: WhoIs (" + to_string( m_workevent->iFlags ) + ") - "
|
||||||
|
+ "[load type: " + m_workevent->Activator->MoverParameters->LoadType + "], "
|
||||||
|
+ "[current load: " + to_string( m_workevent->Activator->MoverParameters->Load, 2 ) + "], "
|
||||||
|
+ "[max load: " + to_string( m_workevent->Activator->MoverParameters->MaxLoad, 2 ) + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_workevent->iFlags & update_memadd)
|
||||||
|
{ // jeśli miejsce docelowe pojazdu
|
||||||
|
m_workevent->Params[ 9 ].asMemCell->UpdateValues(
|
||||||
|
m_workevent->Activator->asDestination, // adres docelowy
|
||||||
|
m_workevent->Activator->DirectionGet(), // kierunek pojazdu względem czoła składu (1=zgodny,-1=przeciwny)
|
||||||
|
m_workevent->Activator->MoverParameters->Power, // moc pojazdu silnikowego: 0 dla wagonu
|
||||||
|
m_workevent->iFlags & (update_memstring | update_memval1 | update_memval2));
|
||||||
|
|
||||||
|
WriteLog(
|
||||||
|
"Type: WhoIs (" + to_string( m_workevent->iFlags ) + ") - "
|
||||||
|
+ "[destination: " + m_workevent->Activator->asDestination + "], "
|
||||||
|
+ "[direction: " + to_string( m_workevent->Activator->DirectionGet() ) + "], "
|
||||||
|
+ "[engine power: " + to_string( m_workevent->Activator->MoverParameters->Power, 2 ) + "]" );
|
||||||
|
}
|
||||||
|
else if (m_workevent->Activator->Mechanik)
|
||||||
|
if (m_workevent->Activator->Mechanik->Primary())
|
||||||
|
{ // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera!
|
||||||
|
m_workevent->Params[ 9 ].asMemCell->UpdateValues(
|
||||||
|
m_workevent->Activator->Mechanik->TrainName(),
|
||||||
|
m_workevent->Activator->Mechanik->StationCount() - m_workevent->Activator->Mechanik->StationIndex(), // ile przystanków do końca
|
||||||
|
m_workevent->Activator->Mechanik->IsStop() ? 1 :
|
||||||
|
0, // 1, gdy ma tu zatrzymanie
|
||||||
|
m_workevent->iFlags);
|
||||||
|
WriteLog("Train detected: " + m_workevent->Activator->Mechanik->TrainName());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_LogValues: {
|
||||||
|
// zapisanie zawartości komórki pamięci do logu
|
||||||
|
if( m_workevent->Params[ 9 ].asMemCell ) {
|
||||||
|
// jeśli była podana nazwa komórki
|
||||||
|
WriteLog( "Memcell \"" + m_workevent->asNodeName + "\": "
|
||||||
|
+ m_workevent->Params[ 9 ].asMemCell->Text() + " "
|
||||||
|
+ std::to_string( m_workevent->Params[ 9 ].asMemCell->Value1() ) + " "
|
||||||
|
+ std::to_string( m_workevent->Params[ 9 ].asMemCell->Value2() ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: re-enable when cell manager is in place
|
||||||
|
/*
|
||||||
|
// lista wszystkich
|
||||||
|
for( TGroundNode *Current = nRootOfType[ TP_MEMCELL ]; Current; Current = Current->nNext ) {
|
||||||
|
WriteLog( "Memcell \"" + Current->asName + "\": "
|
||||||
|
+ Current->MemCell->Text() + " "
|
||||||
|
+ std::to_string( Current->MemCell->Value1() ) + " "
|
||||||
|
+ std::to_string( Current->MemCell->Value2() ) );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Voltage: // zmiana napięcia w zasilaczu (TractionPowerSource)
|
||||||
|
if (m_workevent->Params[9].psPower)
|
||||||
|
{ // na razie takie chamskie ustawienie napięcia zasilania
|
||||||
|
WriteLog("Type: Voltage");
|
||||||
|
m_workevent->Params[9].psPower->VoltageSet(m_workevent->Params[0].asdouble);
|
||||||
|
}
|
||||||
|
case tp_Friction: // zmiana tarcia na scenerii
|
||||||
|
{ // na razie takie chamskie ustawienie napięcia zasilania
|
||||||
|
WriteLog("Type: Friction");
|
||||||
|
Global::fFriction = (m_workevent->Params[0].asdouble);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tp_Message: // wyświetlenie komunikatu
|
||||||
|
break;
|
||||||
|
} // switch (tmpEvent->Type)
|
||||||
|
} // if (tmpEvent->bEnabled)
|
||||||
|
} // while
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, initializes events after deserialization from scenario file
|
||||||
|
void
|
||||||
|
event_manager::InitEvents() {
|
||||||
|
|
||||||
|
//łączenie eventów z pozostałymi obiektami
|
||||||
|
for( auto *Current : m_events ) {
|
||||||
|
|
||||||
|
switch (Current->Type) {
|
||||||
|
|
||||||
|
case tp_AddValues: // sumowanie wartości
|
||||||
|
case tp_UpdateValues: { // zmiana wartości
|
||||||
|
auto *cell = simulation::Memory.find( Current->asNodeName ); // nazwa komórki powiązanej z eventem
|
||||||
|
if( cell ) { // McZapkie-100302
|
||||||
|
if( Current->iFlags & ( conditional_trackoccupied | conditional_trackfree ) ) {
|
||||||
|
// jeśli chodzi o zajetosc toru (tor może być inny, niż wpisany w komórce)
|
||||||
|
// nazwa toru ta sama, co nazwa komórki
|
||||||
|
Current->Params[ 9 ].asTrack = simulation::Paths.find( Current->asNodeName );
|
||||||
|
if( Current->Params[ 9 ].asTrack == nullptr ) {
|
||||||
|
ErrorLog( "Bad event: track \"" + Current->asNodeName + "\" referenced in event \"" + Current->asName + "\" doesn't exist" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Current->Params[ 4 ].asLocation = &( cell->location() );
|
||||||
|
Current->Params[ 5 ].asMemCell = cell; // komórka do aktualizacji
|
||||||
|
if( Current->iFlags & ( conditional_memcompare ) ) {
|
||||||
|
// komórka do badania warunku
|
||||||
|
Current->Params[ 9 ].asMemCell = cell;
|
||||||
|
}
|
||||||
|
if( false == cell->asTrackName.empty() ) {
|
||||||
|
// tor powiązany z komórką powiązaną z eventem
|
||||||
|
// tu potrzebujemy wskaźnik do komórki w (tmp)
|
||||||
|
Current->Params[ 6 ].asTrack = simulation::Paths.find( cell->asTrackName );
|
||||||
|
if( Current->Params[ 6 ].asTrack == nullptr ) {
|
||||||
|
ErrorLog( "Bad memcell: track \"" + cell->asTrackName + "\" referenced in memcell \"" + cell->name() + "\" doesn't exist" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Current->Params[ 6 ].asTrack = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// nie ma komórki, to nie będzie działał poprawnie
|
||||||
|
Current->Type = tp_Ignored; // deaktywacja
|
||||||
|
ErrorLog( "Bad event: event \"" + Current->asName + "\" cannot find memcell \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_LogValues: {
|
||||||
|
// skojarzenie z memcell
|
||||||
|
if( Current->asNodeName.empty() ) { // brak skojarzenia daje logowanie wszystkich
|
||||||
|
Current->Params[ 9 ].asMemCell = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case tp_GetValues:
|
||||||
|
case tp_WhoIs: {
|
||||||
|
auto *cell = simulation::Memory.find( Current->asNodeName );
|
||||||
|
if( cell ) {
|
||||||
|
Current->Params[ 8 ].asLocation = &( cell->location() );
|
||||||
|
Current->Params[ 9 ].asMemCell = cell;
|
||||||
|
if( ( Current->Type == tp_GetValues )
|
||||||
|
&& ( cell->IsVelocity() ) ) {
|
||||||
|
// jeśli odczyt komórki a komórka zawiera komendę SetVelocity albo ShuntVelocity
|
||||||
|
// to event nie będzie dodawany do kolejki
|
||||||
|
Current->bEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// nie ma komórki, to nie będzie działał poprawnie
|
||||||
|
Current->Type = tp_Ignored; // deaktywacja
|
||||||
|
ErrorLog( "Bad event: event \"" + Current->asName + "\" cannot find memcell \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_CopyValues: {
|
||||||
|
// skopiowanie komórki do innej
|
||||||
|
auto *cell = simulation::Memory.find( Current->asNodeName ); // komórka docelowa
|
||||||
|
if( cell ) {
|
||||||
|
Current->Params[ 4 ].asLocation = &( cell->location() );
|
||||||
|
Current->Params[ 5 ].asMemCell = cell; // komórka docelowa
|
||||||
|
if( false == cell->asTrackName.empty() ) {
|
||||||
|
// tor powiązany z komórką powiązaną z eventem
|
||||||
|
// tu potrzebujemy wskaźnik do komórki w (tmp)
|
||||||
|
Current->Params[ 6 ].asTrack = simulation::Paths.find( cell->asTrackName );
|
||||||
|
if( Current->Params[ 6 ].asTrack == nullptr ) {
|
||||||
|
ErrorLog( "Bad memcell: track \"" + cell->asTrackName + "\" referenced in memcell \"" + cell->name() + "\" doesn't exists" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Current->Params[ 6 ].asTrack = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad event: copyvalues event \"" + Current->asName + "\" cannot find memcell \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
std::string const cellastext { Current->Params[ 9 ].asText };
|
||||||
|
cell = simulation::Memory.find( Current->Params[ 9 ].asText ); // komórka źódłowa
|
||||||
|
SafeDeleteArray( Current->Params[ 9 ].asText ); // usunięcie nazwy komórki
|
||||||
|
if( cell != nullptr ) {
|
||||||
|
Current->Params[ 8 ].asLocation = &( cell->location() );
|
||||||
|
Current->Params[ 9 ].asMemCell = cell; // komórka źródłowa
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad event: copyvalues event \"" + Current->asName + "\" cannot find memcell \"" + cellastext + "\"" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Animation: {
|
||||||
|
// animacja modelu
|
||||||
|
// retrieve target name parameter
|
||||||
|
std::string const cellastext = Current->Params[ 9 ].asText;
|
||||||
|
SafeDeleteArray( Current->Params[ 9 ].asText );
|
||||||
|
// egzemplarz modelu do animowania
|
||||||
|
auto *instance = simulation::Instances.find( Current->asNodeName );
|
||||||
|
if( instance ) {
|
||||||
|
if( Current->Params[ 0 ].asInt == 4 ) {
|
||||||
|
// model dla całomodelowych animacji
|
||||||
|
Current->Params[ 9 ].asModel = instance;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// standardowo przypisanie submodelu
|
||||||
|
Current->Params[ 9 ].asAnimContainer = instance->GetContainer( cellastext ); // submodel
|
||||||
|
if( Current->Params[ 9 ].asAnimContainer ) {
|
||||||
|
Current->Params[ 9 ].asAnimContainer->WillBeAnimated(); // oflagowanie animacji
|
||||||
|
if( Current->Params[ 9 ].asAnimContainer->Event() == nullptr ) {
|
||||||
|
// nie szukać, gdy znaleziony
|
||||||
|
Current->Params[ 9 ].asAnimContainer->EventAssign(
|
||||||
|
FindEvent( Current->asNodeName + "." + cellastext + ":done" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad event: animation event \"" + Current->asName + "\" cannot find model instance \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tp_Lights: {
|
||||||
|
// zmiana świeteł modelu
|
||||||
|
auto *instance = simulation::Instances.find( Current->asNodeName );
|
||||||
|
if( instance )
|
||||||
|
Current->Params[ 9 ].asModel = instance;
|
||||||
|
else
|
||||||
|
ErrorLog( "Bad event: lights event \"" + Current->asName + "\" cannot find model instance \"" + Current->asNodeName + "\"" );
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case tp_Visible: {
|
||||||
|
// ukrycie albo przywrócenie obiektu
|
||||||
|
tmp = FindGroundNode( Current->asNodeName, TP_MODEL ); // najpierw model
|
||||||
|
if( !tmp )
|
||||||
|
tmp = FindGroundNode( Current->asNodeName, TP_TRACK ); // albo tory?
|
||||||
|
if( !tmp )
|
||||||
|
tmp = FindGroundNode( Current->asNodeName, TP_TRACTION ); // może druty?
|
||||||
|
if( tmp )
|
||||||
|
Current->Params[ 9 ].nGroundNode = tmp;
|
||||||
|
else
|
||||||
|
ErrorLog( "Bad event: visibility event \"" + Current->asName + "\" cannot find item \"" + Current->asNodeName + "\"" );
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
case tp_Switch: {
|
||||||
|
// przełożenie zwrotnicy albo zmiana stanu obrotnicy
|
||||||
|
auto *track = simulation::Paths.find( Current->asNodeName );
|
||||||
|
if( track ) {
|
||||||
|
// dowiązanie toru
|
||||||
|
if( track->iAction == NULL ) {
|
||||||
|
// jeśli nie jest zwrotnicą ani obrotnicą to będzie się zmieniał stan uszkodzenia
|
||||||
|
track->iAction |= 0x100;
|
||||||
|
}
|
||||||
|
Current->Params[ 9 ].asTrack = track;
|
||||||
|
if( ( Current->Params[ 0 ].asInt == 0 )
|
||||||
|
&& ( Current->Params[ 2 ].asdouble >= 0.0 ) ) {
|
||||||
|
// jeśli przełącza do stanu 0 & jeśli jest zdefiniowany dodatkowy ruch iglic
|
||||||
|
// przesłanie parametrów
|
||||||
|
Current->Params[ 9 ].asTrack->Switch(
|
||||||
|
Current->Params[ 0 ].asInt,
|
||||||
|
Current->Params[ 1 ].asdouble,
|
||||||
|
Current->Params[ 2 ].asdouble );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad event: switch event \"" + Current->asName + "\" cannot find track \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case tp_Sound: {
|
||||||
|
// odtworzenie dźwięku
|
||||||
|
tmp = FindGroundNode( Current->asNodeName, TP_SOUND );
|
||||||
|
if( tmp )
|
||||||
|
Current->Params[ 9 ].tsTextSound = tmp->tsStaticSound;
|
||||||
|
else
|
||||||
|
ErrorLog( "Bad event: sound event \"" + Current->asName + "\" cannot find static sound \"" + Current->asNodeName + "\"" );
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
case tp_TrackVel: {
|
||||||
|
// ustawienie prędkości na torze
|
||||||
|
if( false == Current->asNodeName.empty() ) {
|
||||||
|
auto *track = simulation::Paths.find( Current->asNodeName );
|
||||||
|
if( track ) {
|
||||||
|
// flaga zmiany prędkości toru jest istotna dla skanowania
|
||||||
|
track->iAction |= 0x200;
|
||||||
|
Current->Params[ 9 ].asTrack = track;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad event: track velocity event \"" + Current->asName + "\" cannot find track \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case tp_DynVel: {
|
||||||
|
// komunikacja z pojazdem o konkretnej nazwie
|
||||||
|
if( Current->asNodeName == "activator" )
|
||||||
|
Current->Params[ 9 ].asDynamic = nullptr;
|
||||||
|
else {
|
||||||
|
tmp = FindGroundNode( Current->asNodeName, TP_DYNAMIC );
|
||||||
|
if( tmp )
|
||||||
|
Current->Params[ 9 ].asDynamic = tmp->DynamicObject;
|
||||||
|
else
|
||||||
|
Error( "Bad event: vehicle velocity event \"" + Current->asName + "\" cannot find vehicle \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
case tp_Multiple: {
|
||||||
|
std::string cellastext;
|
||||||
|
if( Current->Params[ 9 ].asText != nullptr ) { // przepisanie nazwy do bufora
|
||||||
|
cellastext = Current->Params[ 9 ].asText;
|
||||||
|
SafeDeleteArray( Current->Params[ 9 ].asText );
|
||||||
|
Current->Params[ 9 ].asPointer = nullptr; // zerowanie wskaźnika, aby wykryć brak obeiktu
|
||||||
|
}
|
||||||
|
if( Current->iFlags & ( conditional_trackoccupied | conditional_trackfree ) ) {
|
||||||
|
// jeśli chodzi o zajetosc toru
|
||||||
|
Current->Params[ 9 ].asTrack = simulation::Paths.find( cellastext );
|
||||||
|
if( Current->Params[ 9 ].asTrack == nullptr ) {
|
||||||
|
ErrorLog( "Bad event: multi-event \"" + Current->asName + "\" cannot find track \"" + cellastext + "\"" );
|
||||||
|
Current->iFlags &= ~( conditional_trackoccupied | conditional_trackfree ); // zerowanie flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( Current->iFlags & ( conditional_memstring | conditional_memval1 | conditional_memval2 ) ) {
|
||||||
|
// jeśli chodzi o komorke pamieciową
|
||||||
|
Current->Params[ 9 ].asMemCell = simulation::Memory.find( cellastext );
|
||||||
|
if( Current->Params[ 9 ].asMemCell == nullptr ) {
|
||||||
|
ErrorLog( "Bad event: multi-event \"" + Current->asName + "\" cannot find memory cell \"" + cellastext + "\"" );
|
||||||
|
Current->iFlags &= ~( conditional_memstring | conditional_memval1 | conditional_memval2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( int i = 0; i < 8; ++i ) {
|
||||||
|
if( Current->Params[ i ].asText != nullptr ) {
|
||||||
|
cellastext = Current->Params[ i ].asText;
|
||||||
|
SafeDeleteArray( Current->Params[ i ].asText );
|
||||||
|
Current->Params[ i ].asEvent = FindEvent( cellastext );
|
||||||
|
if( Current->Params[ i ].asEvent == nullptr ) {
|
||||||
|
// Ra: tylko w logu informacja o braku
|
||||||
|
ErrorLog( "Bad event: multi-event \"" + Current->asName + "\" cannot find event \"" + cellastext + "\"" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case tp_Voltage: {
|
||||||
|
// zmiana napięcia w zasilaczu (TractionPowerSource)
|
||||||
|
if( !Current->asNodeName.empty() ) {
|
||||||
|
tmp = FindGroundNode( Current->asNodeName, TP_TRACTIONPOWERSOURCE ); // podłączenie zasilacza
|
||||||
|
if( tmp )
|
||||||
|
Current->Params[ 9 ].psPower = tmp->psTractionPowerSource;
|
||||||
|
else
|
||||||
|
ErrorLog( "Bad event: voltage event \"" + Current->asName + "\" cannot find power source \"" + Current->asNodeName + "\"" );
|
||||||
|
}
|
||||||
|
Current->asNodeName = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
case tp_Message: {
|
||||||
|
// wyświetlenie komunikatu
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // switch
|
||||||
|
if( Current->fDelay < 0 ) {
|
||||||
|
AddToQuery( Current, nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for (TGroundNode *Current = nRootOfType[TP_MEMCELL]; Current; Current = Current->nNext)
|
||||||
|
{ // Ra: eventy komórek pamięci, wykonywane po wysłaniu komendy do zatrzymanego pojazdu
|
||||||
|
Current->MemCell->AssignEvents( FindEvent( Current->asName + ":sent" ) );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy method, verifies condition for specified event
|
||||||
|
bool
|
||||||
|
event_manager::EventConditon( TEvent *Event ) {
|
||||||
|
|
||||||
|
if (Event->iFlags <= update_only)
|
||||||
|
return true; // bezwarunkowo
|
||||||
|
|
||||||
|
if (Event->iFlags & conditional_trackoccupied)
|
||||||
|
return (!Event->Params[9].asTrack->IsEmpty());
|
||||||
|
else if (Event->iFlags & conditional_trackfree)
|
||||||
|
return (Event->Params[9].asTrack->IsEmpty());
|
||||||
|
else if (Event->iFlags & conditional_propability)
|
||||||
|
{
|
||||||
|
double rprobability = Random();
|
||||||
|
WriteLog( "Random integer: " + std::to_string( rprobability ) + " / " + std::to_string( Event->Params[ 10 ].asdouble ) );
|
||||||
|
return (Event->Params[10].asdouble > rprobability);
|
||||||
|
}
|
||||||
|
else if( Event->iFlags & conditional_memcompare ) {
|
||||||
|
// porównanie wartości
|
||||||
|
if( nullptr == Event->Params[9].asMemCell ) {
|
||||||
|
|
||||||
|
ErrorLog( "Event " + Event->asName + " trying conditional_memcompare with nonexistent memcell" );
|
||||||
|
return true; // though this is technically error, we report success to maintain backward compatibility
|
||||||
|
}
|
||||||
|
auto const comparisonresult =
|
||||||
|
m_workevent->Params[ 9 ].asMemCell->Compare(
|
||||||
|
( Event->Params[ 10 ].asText != nullptr ?
|
||||||
|
Event->Params[ 10 ].asText :
|
||||||
|
"" ),
|
||||||
|
Event->Params[ 11 ].asdouble,
|
||||||
|
Event->Params[ 12 ].asdouble,
|
||||||
|
Event->iFlags );
|
||||||
|
|
||||||
|
std::string comparisonlog = "Type: MemCompare - ";
|
||||||
|
|
||||||
|
comparisonlog +=
|
||||||
|
"[" + Event->Params[ 9 ].asMemCell->Text() + "]"
|
||||||
|
+ " [" + to_string( Event->Params[ 9 ].asMemCell->Value1(), 2 ) + "]"
|
||||||
|
+ " [" + to_string( m_workevent->Params[ 9 ].asMemCell->Value2(), 2 ) + "]";
|
||||||
|
|
||||||
|
comparisonlog += (
|
||||||
|
true == comparisonresult ?
|
||||||
|
" == " :
|
||||||
|
" != " );
|
||||||
|
|
||||||
|
comparisonlog += (
|
||||||
|
TestFlag( Event->iFlags, conditional_memstring ) ?
|
||||||
|
"[" + std::string( m_workevent->Params[ 10 ].asText ) + "]" :
|
||||||
|
"[*]" );
|
||||||
|
comparisonlog += (
|
||||||
|
TestFlag( m_workevent->iFlags, conditional_memval1 ) ?
|
||||||
|
" [" + to_string( m_workevent->Params[ 11 ].asdouble, 2 ) + "]" :
|
||||||
|
" [*]" );
|
||||||
|
comparisonlog += (
|
||||||
|
TestFlag( m_workevent->iFlags, conditional_memval2 ) ?
|
||||||
|
" [" + to_string( m_workevent->Params[ 12 ].asdouble, 2 ) + "]" :
|
||||||
|
" [*]" );
|
||||||
|
|
||||||
|
WriteLog( comparisonlog );
|
||||||
|
return comparisonresult;
|
||||||
|
}
|
||||||
|
// unrecognized request
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
58
Event.h
58
Event.h
@@ -11,9 +11,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
#include "Classes.h"
|
#include "classes.h"
|
||||||
|
|
||||||
using namespace Math3D;
|
|
||||||
|
|
||||||
enum TEventType {
|
enum TEventType {
|
||||||
tp_Unknown,
|
tp_Unknown,
|
||||||
@@ -63,6 +61,7 @@ union TParam
|
|||||||
void *asPointer;
|
void *asPointer;
|
||||||
TMemCell *asMemCell;
|
TMemCell *asMemCell;
|
||||||
TGroundNode *nGroundNode;
|
TGroundNode *nGroundNode;
|
||||||
|
glm::dvec3 const *asLocation;
|
||||||
TTrack *asTrack;
|
TTrack *asTrack;
|
||||||
TAnimModel *asModel;
|
TAnimModel *asModel;
|
||||||
TAnimContainer *asAnimContainer;
|
TAnimContainer *asAnimContainer;
|
||||||
@@ -87,9 +86,10 @@ class TEvent // zmienne: ev*
|
|||||||
std::string asName;
|
std::string asName;
|
||||||
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
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
TEvent *evNext2 = nullptr;
|
TEvent *evNext2 = nullptr;
|
||||||
|
#endif
|
||||||
TEventType Type = tp_Unknown;
|
TEventType Type = tp_Unknown;
|
||||||
double fStartTime = 0.0;
|
double fStartTime = 0.0;
|
||||||
double fDelay = 0.0;
|
double fDelay = 0.0;
|
||||||
@@ -103,15 +103,61 @@ class TEvent // zmienne: ev*
|
|||||||
TEvent(std::string const &m = "");
|
TEvent(std::string const &m = "");
|
||||||
~TEvent();
|
~TEvent();
|
||||||
void Init();
|
void Init();
|
||||||
void Load(cParser *parser, vector3 *org);
|
void Load(cParser *parser, Math3D::vector3 const &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 provided event to the collection. returns: true on success
|
||||||
|
// TODO: return handle instead of pointer
|
||||||
|
bool
|
||||||
|
insert( TEvent *Event );
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// types
|
||||||
|
using event_sequence = std::deque<TEvent *>;
|
||||||
|
using event_map = std::unordered_map<std::string, std::size_t>;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ float Global::AnisotropicFiltering = 8.0f; // requested level of anisotropic fil
|
|||||||
bool Global::bUseVBO = true; // czy jest VBO w karcie graficznej (czy użyć)
|
bool Global::bUseVBO = true; // czy jest VBO w karcie graficznej (czy użyć)
|
||||||
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
|
||||||
@@ -1008,7 +1008,11 @@ TDynamicObject *Global::CouplerNearest()
|
|||||||
|
|
||||||
bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
|
bool Global::AddToQuery(TEvent *event, TDynamicObject *who)
|
||||||
{
|
{
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
return pGround->AddToQuery(event, who);
|
return pGround->AddToQuery(event, who);
|
||||||
|
#else
|
||||||
|
return simulation::Events.AddToQuery( event, who );
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
357
Ground.cpp
357
Ground.cpp
@@ -20,7 +20,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "usefull.h"
|
#include "usefull.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "renderer.h"
|
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "EvLaunch.h"
|
#include "EvLaunch.h"
|
||||||
#include "TractionPower.h"
|
#include "TractionPower.h"
|
||||||
@@ -34,9 +33,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Data.h"
|
#include "Data.h"
|
||||||
#include "parser.h" //Tolaris-010603
|
#include "parser.h" //Tolaris-010603
|
||||||
#include "Driver.h"
|
#include "Driver.h"
|
||||||
#include "Console.h"
|
|
||||||
#include "Names.h"
|
|
||||||
#include "world.h"
|
|
||||||
#include "uilayer.h"
|
#include "uilayer.h"
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -47,7 +43,6 @@ extern "C"
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool bCondition; // McZapkie: do testowania warunku na event multiple
|
bool bCondition; // McZapkie: do testowania warunku na event multiple
|
||||||
std::string LogComment;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Obiekt renderujący siatkę jest sztucznie tworzonym obiektem pomocniczym,
|
// Obiekt renderujący siatkę jest sztucznie tworzonym obiektem pomocniczym,
|
||||||
@@ -123,6 +118,8 @@ TGroundNode::~TGroundNode()
|
|||||||
case GL_TRIANGLES:
|
case GL_TRIANGLES:
|
||||||
SafeDelete( Piece );
|
SafeDelete( Piece );
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -144,7 +141,7 @@ TGroundNode::TGroundNode( TGroundNodeType t ) :
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TP_TRACK: {
|
case TP_TRACK: {
|
||||||
pTrack = new TTrack( this );
|
pTrack = new TTrack( asName );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -314,9 +311,8 @@ void TSubRect::NodeAdd(TGroundNode *Node)
|
|||||||
// przygotowanie sektora do renderowania
|
// przygotowanie sektora do renderowania
|
||||||
void TSubRect::Sort() {
|
void TSubRect::Sort() {
|
||||||
|
|
||||||
if( tTracks != nullptr ) {
|
SafeDeleteArray( tTracks );
|
||||||
SafeDelete( tTracks );
|
|
||||||
}
|
|
||||||
if( iTracks > 0 ) {
|
if( iTracks > 0 ) {
|
||||||
tTracks = new TTrack *[ iTracks ]; // tworzenie tabeli torów do renderowania pojazdów
|
tTracks = new TTrack *[ iTracks ]; // tworzenie tabeli torów do renderowania pojazdów
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -414,12 +410,20 @@ void TSubRect::LoadNodes() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TP_TRACK:
|
case TP_TRACK:
|
||||||
if( node->pTrack->bVisible ) { // bo tory zabezpieczające są niewidoczne
|
if( node->pTrack->visible() ) { // bo tory zabezpieczające są niewidoczne
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
node->pTrack->create_geometry( m_geometrybank, node->m_rootposition );
|
||||||
|
#else
|
||||||
node->pTrack->create_geometry( m_geometrybank );
|
node->pTrack->create_geometry( m_geometrybank );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TP_TRACTION:
|
case TP_TRACTION:
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
node->hvTraction->create_geometry( m_geometrybank, node->m_rootposition );
|
node->hvTraction->create_geometry( m_geometrybank, node->m_rootposition );
|
||||||
|
#else
|
||||||
|
node->hvTraction->create_geometry( m_geometrybank );
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
default: { break; }
|
default: { break; }
|
||||||
}
|
}
|
||||||
@@ -448,16 +452,16 @@ TGroundRect::Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pSubRects = new TSubRect[ iNumSubRects * iNumSubRects ];
|
pSubRects = new TSubRect[ iNumSubRects * iNumSubRects ];
|
||||||
float const subrectsize = 1000.0f / iNumSubRects;
|
auto const subrectsize = 1000.0 / iNumSubRects;
|
||||||
for( int column = 0; column < iNumSubRects; ++column ) {
|
for( int column = 0; column < iNumSubRects; ++column ) {
|
||||||
for( int row = 0; row < iNumSubRects; ++row ) {
|
for( int row = 0; row < iNumSubRects; ++row ) {
|
||||||
auto subcell = FastGetSubRect( column, row );
|
auto subcell = FastGetSubRect( column, row );
|
||||||
auto &area = subcell->m_area;
|
auto &area = subcell->m_area;
|
||||||
area.center =
|
area.center =
|
||||||
m_area.center
|
m_area.center
|
||||||
- glm::vec3( 500.0f, 0.0f, 500.0f ) // 'upper left' corner of rectangle
|
- glm::dvec3( 500.0, 0.0, 500.0 ) // 'upper left' corner of rectangle
|
||||||
+ glm::vec3( subrectsize * 0.5f, 0.0f, subrectsize * 0.5f ) // center of sub-rectangle
|
+ glm::dvec3( subrectsize * 0.5, 0.0, subrectsize * 0.5 ) // center of sub-rectangle
|
||||||
+ glm::vec3( subrectsize * column, 0.0f, subrectsize * row );
|
+ glm::dvec3( subrectsize * column, 0.0, subrectsize * row );
|
||||||
area.radius = subrectsize * M_SQRT2;
|
area.radius = subrectsize * M_SQRT2;
|
||||||
// all subcells share the same geometry bank with their parent, to reduce buffer switching during render
|
// all subcells share the same geometry bank with their parent, to reduce buffer switching during render
|
||||||
subcell->m_geometrybank = m_geometrybank;
|
subcell->m_geometrybank = m_geometrybank;
|
||||||
@@ -507,7 +511,7 @@ TGroundRect::NodeAdd( TGroundNode *Node ) {
|
|||||||
|
|
||||||
// compares two provided nodes, returns true if their content can be merged
|
// compares two provided nodes, returns true if their content can be merged
|
||||||
bool
|
bool
|
||||||
TGroundRect::mergeable( TGroundNode const &Left, TGroundNode const &Right ) {
|
TGroundRect::mergeable( TGroundNode const &Left, TGroundNode const &Right ) const {
|
||||||
// since view ranges and transparency type for all nodes put through this method are guaranteed to be equal,
|
// since view ranges and transparency type for all nodes put through this method are guaranteed to be equal,
|
||||||
// we can skip their tests and only do the material check.
|
// we can skip their tests and only do the material check.
|
||||||
// TODO, TBD: material as dedicated type, and refactor this method into a simple equality test
|
// TODO, TBD: material as dedicated type, and refactor this method into a simple equality test
|
||||||
@@ -553,6 +557,7 @@ TGround::~TGround()
|
|||||||
|
|
||||||
void TGround::Free()
|
void TGround::Free()
|
||||||
{
|
{
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
TEvent *tmp;
|
TEvent *tmp;
|
||||||
for (TEvent *Current = RootEvent; Current;)
|
for (TEvent *Current = RootEvent; Current;)
|
||||||
{
|
{
|
||||||
@@ -560,6 +565,7 @@ void TGround::Free()
|
|||||||
Current = Current->evNext2;
|
Current = Current->evNext2;
|
||||||
delete tmp;
|
delete tmp;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
TGroundNode *tmpn;
|
TGroundNode *tmpn;
|
||||||
for (int i = 0; i < TP_LAST; ++i)
|
for (int i = 0; i < TP_LAST; ++i)
|
||||||
{
|
{
|
||||||
@@ -598,7 +604,8 @@ TGroundNode * TGround::DynamicFind(std::string const &Name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TGround::DynamicList(bool all)
|
void
|
||||||
|
TGround::DynamicList(bool all)
|
||||||
{ // odesłanie nazw pojazdów dostępnych na scenerii (nazwy, szczególnie wagonów, mogą się
|
{ // odesłanie nazw pojazdów dostępnych na scenerii (nazwy, szczególnie wagonów, mogą się
|
||||||
// powtarzać!)
|
// powtarzać!)
|
||||||
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
||||||
@@ -607,45 +614,23 @@ void TGround::DynamicList(bool all)
|
|||||||
WyslijString("none", 6); // informacja o końcu listy
|
WyslijString("none", 6); // informacja o końcu listy
|
||||||
};
|
};
|
||||||
|
|
||||||
TGroundNode * TGround::FindGroundNode(std::string asNameToFind, TGroundNodeType iNodeType)
|
// wyszukiwanie obiektu o podanej nazwie i konkretnym typie
|
||||||
{ // wyszukiwanie obiektu o podanej nazwie i konkretnym typie
|
TGroundNode *
|
||||||
if ((iNodeType == TP_TRACK) || (iNodeType == TP_MEMCELL) || (iNodeType == TP_MODEL))
|
TGround::FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType) {
|
||||||
{ // wyszukiwanie w drzewie binarnym
|
|
||||||
/*
|
|
||||||
switch( iNodeType ) {
|
|
||||||
|
|
||||||
case TP_TRACK: {
|
if( ( iNodeType == TP_TRACK )
|
||||||
auto const lookup = m_trackmap.find( asNameToFind );
|
|| ( iNodeType == TP_MEMCELL )
|
||||||
return
|
|| ( iNodeType == TP_MODEL ) ) {
|
||||||
lookup != m_trackmap.end() ?
|
// wyszukiwanie w drzewie binarnym
|
||||||
lookup->second :
|
return m_nodemap.Find( iNodeType, asNameToFind );
|
||||||
nullptr;
|
|
||||||
}
|
}
|
||||||
case TP_MODEL: {
|
// standardowe wyszukiwanie liniowe
|
||||||
auto const lookup = m_modelmap.find( asNameToFind );
|
for( TGroundNode *Current = nRootOfType[ iNodeType ]; Current != nullptr; Current = Current->nNext ) {
|
||||||
return
|
if( Current->asName == asNameToFind ) {
|
||||||
lookup != m_modelmap.end() ?
|
return Current;
|
||||||
lookup->second :
|
|
||||||
nullptr;
|
|
||||||
}
|
|
||||||
case TP_MEMCELL: {
|
|
||||||
auto const lookup = m_memcellmap.find( asNameToFind );
|
|
||||||
return
|
|
||||||
lookup != m_memcellmap.end() ?
|
|
||||||
lookup->second :
|
|
||||||
nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
*/
|
|
||||||
return m_trackmap.Find( iNodeType, asNameToFind );
|
|
||||||
}
|
|
||||||
// standardowe wyszukiwanie liniowe
|
|
||||||
TGroundNode *Current;
|
|
||||||
for (Current = nRootOfType[iNodeType]; Current; Current = Current->nNext)
|
|
||||||
if (Current->asName == asNameToFind)
|
|
||||||
return Current;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TGroundRect *
|
TGroundRect *
|
||||||
@@ -905,7 +890,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
switch (tmp->iType)
|
switch (tmp->iType)
|
||||||
{
|
{
|
||||||
case TP_TRACTION:
|
case TP_TRACTION:
|
||||||
tmp->hvTraction = new TTraction();
|
tmp->hvTraction = new TTraction( tmp->asName );
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
tmp->hvTraction->asPowerSupplyName = token; // nazwa zasilacza
|
tmp->hvTraction->asPowerSupplyName = token; // nazwa zasilacza
|
||||||
@@ -989,8 +974,6 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
if (token.compare("endtraction") != 0)
|
if (token.compare("endtraction") != 0)
|
||||||
Error("ENDTRACTION delimiter missing! " + str2 + " found instead.");
|
Error("ENDTRACTION delimiter missing! " + str2 + " found instead.");
|
||||||
tmp->hvTraction->Init(); // przeliczenie parametrów
|
tmp->hvTraction->Init(); // przeliczenie parametrów
|
||||||
// if (Global::bLoadTraction)
|
|
||||||
// tmp->hvTraction->Optimize(); //generowanie DL dla wszystkiego przy wczytywaniu?
|
|
||||||
tmp->pCenter = interpolate( tmp->hvTraction->pPoint2, tmp->hvTraction->pPoint1, 0.5 );
|
tmp->pCenter = interpolate( tmp->hvTraction->pPoint2, tmp->hvTraction->pPoint1, 0.5 );
|
||||||
break;
|
break;
|
||||||
case TP_TRACTIONPOWERSOURCE:
|
case TP_TRACTIONPOWERSOURCE:
|
||||||
@@ -1015,7 +998,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
tmp->MemCell->Load(parser);
|
tmp->MemCell->Load(parser);
|
||||||
if (!tmp->asName.empty()) // jest pusta gdy "none"
|
if (!tmp->asName.empty()) // jest pusta gdy "none"
|
||||||
{ // dodanie do wyszukiwarki
|
{ // dodanie do wyszukiwarki
|
||||||
if( false == m_trackmap.Add( TP_MEMCELL, tmp->asName, tmp ) ) {
|
if( false == m_nodemap.Add( TP_MEMCELL, tmp->asName, tmp ) ) {
|
||||||
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
||||||
ErrorLog( "Duplicated memcell: " + tmp->asName ); // to zgłaszać duplikat
|
ErrorLog( "Duplicated memcell: " + tmp->asName ); // to zgłaszać duplikat
|
||||||
}
|
}
|
||||||
@@ -1033,14 +1016,14 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
tmp->EvLaunch->Load(parser);
|
tmp->EvLaunch->Load(parser);
|
||||||
break;
|
break;
|
||||||
case TP_TRACK:
|
case TP_TRACK:
|
||||||
tmp->pTrack = new TTrack(tmp);
|
tmp->pTrack = new TTrack( tmp->asName );
|
||||||
if (Global::iWriteLogEnabled & 4)
|
if (Global::iWriteLogEnabled & 4)
|
||||||
if (!tmp->asName.empty())
|
if (!tmp->asName.empty())
|
||||||
WriteLog(tmp->asName);
|
WriteLog(tmp->asName);
|
||||||
tmp->pTrack->Load(parser, pOrigin, tmp->asName); // w nazwie może być nazwa odcinka izolowanego
|
tmp->pTrack->Load(parser, pOrigin); // w nazwie może być nazwa odcinka izolowanego
|
||||||
if (!tmp->asName.empty()) // jest pusta gdy "none"
|
if (!tmp->asName.empty()) // jest pusta gdy "none"
|
||||||
{ // dodanie do wyszukiwarki
|
{ // dodanie do wyszukiwarki
|
||||||
if( false == m_trackmap.Add( TP_TRACK, tmp->asName, tmp ) ) {
|
if( false == m_nodemap.Add( TP_TRACK, tmp->asName, tmp ) ) {
|
||||||
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
||||||
ErrorLog( "Duplicated track: " + tmp->asName ); // to zgłaszać duplikat
|
ErrorLog( "Duplicated track: " + tmp->asName ); // to zgłaszać duplikat
|
||||||
}
|
}
|
||||||
@@ -1148,22 +1131,18 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
if (fTrainSetDist < 8.0) // i raczej nie sięga
|
if (fTrainSetDist < 8.0) // i raczej nie sięga
|
||||||
fTrainSetDist =
|
fTrainSetDist =
|
||||||
8.0; // przesuwamy około pół EU07 dla wstecznej zgodności
|
8.0; // przesuwamy około pół EU07 dla wstecznej zgodności
|
||||||
// WriteLog("Dynamic shift: "+AnsiString(fTrainSetDist));
|
|
||||||
/* //Ra: to jednak robi duże problemy - przesunięcie w dynamic jest przesunięciem do
|
auto const length =
|
||||||
tyłu, odwrotnie niż w trainset
|
tmp->DynamicObject->Init(
|
||||||
if (!iTrainSetWehicleNumber) //dla pierwszego jest to przesunięcie (ujemne = do
|
asNodeName, str1, Skin, str3, Track,
|
||||||
tyłu)
|
( tf1 == -1.0 ?
|
||||||
if (tf1!=-1.0) //-1 wyjątkowo oznacza odwrócenie
|
fTrainSetDist :
|
||||||
tf1=-tf1; //a dla kolejnych odległość między sprzęgami (ujemne = wbite)
|
fTrainSetDist - tf1 ),
|
||||||
*/
|
DriverType, tf3, asTrainName, int2, str2, (tf1 == -1.0), str4);
|
||||||
tf3 = tmp->DynamicObject->Init(asNodeName, str1, Skin, str3, Track,
|
if (length != 0.0) // zero oznacza błąd
|
||||||
(tf1 == -1.0 ? fTrainSetDist : fTrainSetDist - tf1),
|
|
||||||
DriverType, tf3, asTrainName, int2, str2, (tf1 == -1.0),
|
|
||||||
str4);
|
|
||||||
if (tf3 != 0.0) // zero oznacza błąd
|
|
||||||
{
|
{
|
||||||
// przesunięcie dla kolejnego, minus bo idziemy w stronę punktu 1
|
// przesunięcie dla kolejnego, minus bo idziemy w stronę punktu 1
|
||||||
fTrainSetDist -= tf3;
|
fTrainSetDist -= length;
|
||||||
tmp->pCenter = tmp->DynamicObject->GetPosition();
|
tmp->pCenter = tmp->DynamicObject->GetPosition();
|
||||||
// automatically establish permanent connections for couplers which specify them in their definitions
|
// automatically establish permanent connections for couplers which specify them in their definitions
|
||||||
if( TempConnectionType[ iTrainSetWehicleNumber ] ) {
|
if( TempConnectionType[ iTrainSetWehicleNumber ] ) {
|
||||||
@@ -1208,7 +1187,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
// we check for presence of security system or sand load, as a way to determine whether the vehicle is a controllable engine
|
// 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
|
// 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
|
// don't have security systems fitted
|
||||||
m_lights.insert( tmp->DynamicObject );
|
simulation::Lights.insert( tmp->DynamicObject );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1257,7 +1236,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
}
|
}
|
||||||
else if( !tmp->asName.empty() ) // jest pusta gdy "none"
|
else if( !tmp->asName.empty() ) // jest pusta gdy "none"
|
||||||
{ // dodanie do wyszukiwarki
|
{ // dodanie do wyszukiwarki
|
||||||
if( false == m_trackmap.Add( TP_MODEL, tmp->asName, tmp ) ) {
|
if( false == m_nodemap.Add( TP_MODEL, tmp->asName, tmp ) ) {
|
||||||
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
||||||
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
|
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
|
||||||
}
|
}
|
||||||
@@ -1310,7 +1289,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
|
|
||||||
tmp->iFlags = 0x200; // flaga usuwania
|
tmp->iFlags = 0x200; // flaga usuwania
|
||||||
tmp->Model = new TAnimModel();
|
tmp->Model = new TAnimModel();
|
||||||
tmp->Model->RaAnglesSet( aRotate.x, tf1 + aRotate.y, aRotate.z ); // dostosowanie do pochylania linii
|
tmp->Model->RaAnglesSet( glm::vec3{ aRotate.x, tf1 + aRotate.y, aRotate.z } ); // dostosowanie do pochylania linii
|
||||||
if( false == tmp->Model->Load( parser, false ) ) {
|
if( false == tmp->Model->Load( parser, false ) ) {
|
||||||
// model nie wczytał się - ignorowanie node
|
// model nie wczytał się - ignorowanie node
|
||||||
delete tmp;
|
delete tmp;
|
||||||
@@ -1320,7 +1299,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
tmp->iFlags |= tmp->Model->Flags(); // ustalenie, czy przezroczysty
|
tmp->iFlags |= tmp->Model->Flags(); // ustalenie, czy przezroczysty
|
||||||
if( false == tmp->asName.empty() ) { // jest pusta gdy "none"
|
if( false == tmp->asName.empty() ) { // jest pusta gdy "none"
|
||||||
// dodanie do wyszukiwarki
|
// dodanie do wyszukiwarki
|
||||||
if( false == m_trackmap.Add( TP_MODEL, tmp->asName, tmp ) ) {
|
if( false == m_nodemap.Add( TP_MODEL, tmp->asName, tmp ) ) {
|
||||||
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
|
||||||
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
|
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
|
||||||
}
|
}
|
||||||
@@ -1652,6 +1631,7 @@ TSubRect * TGround::GetSubRect(int iCol, int iRow)
|
|||||||
return (Rects[bc][br].SafeGetSubRect(sc, sr)); // pobranie małego kwadratu
|
return (Rects[bc][br].SafeGetSubRect(sc, sr)); // pobranie małego kwadratu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
TEvent * TGround::FindEvent(const std::string &asEventName)
|
TEvent * TGround::FindEvent(const std::string &asEventName)
|
||||||
{
|
{
|
||||||
if( asEventName.empty() ) { return nullptr; }
|
if( asEventName.empty() ) { return nullptr; }
|
||||||
@@ -1662,24 +1642,7 @@ TEvent * TGround::FindEvent(const std::string &asEventName)
|
|||||||
lookup->second :
|
lookup->second :
|
||||||
nullptr );
|
nullptr );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
TEvent * TGround::FindEventScan( std::string const &asEventName )
|
|
||||||
{ // wyszukanie eventu z opcją utworzenia niejawnego dla komórek skanowanych
|
|
||||||
auto const lookup = m_eventmap.find( asEventName );
|
|
||||||
auto e = (
|
|
||||||
lookup != m_eventmap.end() ?
|
|
||||||
lookup->second :
|
|
||||||
nullptr );
|
|
||||||
if (e)
|
|
||||||
return e; // jak istnieje, to w porządku
|
|
||||||
if (asEventName.rfind(":scan") != std::string::npos) // jeszcze może być event niejawny
|
|
||||||
{ // no to szukamy komórki pamięci o nazwie zawartej w evencie
|
|
||||||
std::string n = asEventName.substr(0, asEventName.length() - 5); // do dwukropka
|
|
||||||
if( m_trackmap.Find( TP_MEMCELL, n ) != nullptr ) // jeśli jest takowa komórka pamięci
|
|
||||||
e = new TEvent(n); // utworzenie niejawnego eventu jej odczytu
|
|
||||||
}
|
|
||||||
return e; // utworzony albo się nie udało
|
|
||||||
}
|
|
||||||
|
|
||||||
void TGround::FirstInit()
|
void TGround::FirstInit()
|
||||||
{ // ustalanie zależności na scenerii przed wczytaniem pojazdów
|
{ // ustalanie zależności na scenerii przed wczytaniem pojazdów
|
||||||
@@ -1747,14 +1710,14 @@ void TGround::FirstInit()
|
|||||||
|
|
||||||
WriteLog("InitNormals OK");
|
WriteLog("InitNormals OK");
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
InitTracks(); //łączenie odcinków ze sobą i przyklejanie eventów
|
InitTracks(); //łączenie odcinków ze sobą i przyklejanie eventów
|
||||||
WriteLog("InitTracks OK");
|
WriteLog("InitTracks OK");
|
||||||
|
|
||||||
InitTraction(); //łączenie drutów ze sobą
|
InitTraction(); //łączenie drutów ze sobą
|
||||||
WriteLog("InitTraction OK");
|
WriteLog("InitTraction OK");
|
||||||
|
|
||||||
InitEvents();
|
InitEvents();
|
||||||
WriteLog("InitEvents OK");
|
WriteLog( "InitEvents OK" );
|
||||||
|
#endif
|
||||||
|
|
||||||
InitLaunchers();
|
InitLaunchers();
|
||||||
WriteLog("InitLaunchers OK");
|
WriteLog("InitLaunchers OK");
|
||||||
@@ -1919,8 +1882,9 @@ bool TGround::Init(std::string File)
|
|||||||
}
|
}
|
||||||
else if (str == "event")
|
else if (str == "event")
|
||||||
{
|
{
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
TEvent *tmp = new TEvent();
|
TEvent *tmp = new TEvent();
|
||||||
tmp->Load(&parser, &pOrigin);
|
tmp->Load(&parser, pOrigin);
|
||||||
if (tmp->Type == tp_Unknown)
|
if (tmp->Type == tp_Unknown)
|
||||||
delete tmp;
|
delete tmp;
|
||||||
else
|
else
|
||||||
@@ -1983,6 +1947,7 @@ bool TGround::Init(std::string File)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (str == "rotate")
|
else if (str == "rotate")
|
||||||
{
|
{
|
||||||
@@ -2211,7 +2176,7 @@ bool TGround::Init(std::string File)
|
|||||||
Global::iPause &= ~0x10; // koniec pauzy wczytywania
|
Global::iPause &= ~0x10; // koniec pauzy wczytywania
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
bool TGround::InitEvents()
|
bool TGround::InitEvents()
|
||||||
{ //łączenie eventów z pozostałymi obiektami
|
{ //łączenie eventów z pozostałymi obiektami
|
||||||
TGroundNode *tmp, *trk;
|
TGroundNode *tmp, *trk;
|
||||||
@@ -2346,14 +2311,14 @@ bool TGround::InitEvents()
|
|||||||
break;
|
break;
|
||||||
case tp_Visible: // ukrycie albo przywrócenie obiektu
|
case tp_Visible: // ukrycie albo przywrócenie obiektu
|
||||||
tmp = FindGroundNode(Current->asNodeName, TP_MODEL); // najpierw model
|
tmp = FindGroundNode(Current->asNodeName, TP_MODEL); // najpierw model
|
||||||
if (!tmp)
|
|
||||||
tmp = FindGroundNode(Current->asNodeName, TP_TRACTION); // może druty?
|
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
tmp = FindGroundNode(Current->asNodeName, TP_TRACK); // albo tory?
|
tmp = FindGroundNode(Current->asNodeName, TP_TRACK); // albo tory?
|
||||||
|
if (!tmp)
|
||||||
|
tmp = FindGroundNode(Current->asNodeName, TP_TRACTION); // może druty?
|
||||||
if (tmp)
|
if (tmp)
|
||||||
Current->Params[9].nGroundNode = tmp;
|
Current->Params[9].nGroundNode = tmp;
|
||||||
else
|
else
|
||||||
ErrorLog("Bad event: visibility event \"" + Current->asName + "\" cannot find model \"" + Current->asNodeName + "\"");
|
ErrorLog("Bad event: visibility event \"" + Current->asName + "\" cannot find item \"" + Current->asNodeName + "\"");
|
||||||
Current->asNodeName = "";
|
Current->asNodeName = "";
|
||||||
break;
|
break;
|
||||||
case tp_Switch: // przełożenie zwrotnicy albo zmiana stanu obrotnicy
|
case tp_Switch: // przełożenie zwrotnicy albo zmiana stanu obrotnicy
|
||||||
@@ -2490,7 +2455,6 @@ void TGround::InitTracks()
|
|||||||
int iConnection;
|
int iConnection;
|
||||||
|
|
||||||
for (Current = nRootOfType[TP_TRACK]; Current; Current = Current->nNext) {
|
for (Current = nRootOfType[TP_TRACK]; Current; Current = Current->nNext) {
|
||||||
|
|
||||||
Track = Current->pTrack;
|
Track = Current->pTrack;
|
||||||
// assign track events
|
// assign track events
|
||||||
Track->AssignEvents(
|
Track->AssignEvents(
|
||||||
@@ -2513,7 +2477,6 @@ void TGround::InitTracks()
|
|||||||
FindEvent( Current->asName + ":eventall1" ),
|
FindEvent( Current->asName + ":eventall1" ),
|
||||||
FindEvent( Current->asName + ":eventall2" ) );
|
FindEvent( Current->asName + ":eventall2" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Track->eType)
|
switch (Track->eType)
|
||||||
{
|
{
|
||||||
case tt_Table: // obrotnicę też łączymy na starcie z innymi torami
|
case tt_Table: // obrotnicę też łączymy na starcie z innymi torami
|
||||||
@@ -2523,8 +2486,8 @@ void TGround::InitTracks()
|
|||||||
// Track->ModelAssign(tmp->Model->GetContainer(NULL)); //wiązanie toru z modelem
|
// Track->ModelAssign(tmp->Model->GetContainer(NULL)); //wiązanie toru z modelem
|
||||||
// obrotnicy
|
// obrotnicy
|
||||||
Track->RaAssign(
|
Track->RaAssign(
|
||||||
Current, Model ? Model->Model : NULL, FindEvent(Current->asName + ":done"),
|
Current, Model ? Model->Model : NULL, simulation::Events.FindEvent(Current->asName + ":done"),
|
||||||
FindEvent(Current->asName + ":joined")); // wiązanie toru z modelem obrotnicy
|
simulation::Events.FindEvent(Current->asName + ":joined")); // wiązanie toru z modelem obrotnicy
|
||||||
// break; //jednak połączę z sąsiednim, jak ma się wysypywać null track
|
// break; //jednak połączę z sąsiednim, jak ma się wysypywać null track
|
||||||
}
|
}
|
||||||
if (!Model) // jak nie ma modelu
|
if (!Model) // jak nie ma modelu
|
||||||
@@ -2607,15 +2570,18 @@ void TGround::InitTracks()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tt_Switch: // dla rozjazdów szukamy eventów sygnalizacji rozprucia
|
case tt_Switch: // dla rozjazdów szukamy eventów sygnalizacji rozprucia
|
||||||
Track->AssignForcedEvents(FindEvent(Current->asName + ":forced+"),
|
Track->AssignForcedEvents(
|
||||||
FindEvent(Current->asName + ":forced-"));
|
FindEvent( Current->asName + ":forced+" ),
|
||||||
|
FindEvent( Current->asName + ":forced-" ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::string const name = Track->IsolatedName(); // pobranie nazwy odcinka izolowanego
|
std::string const name = Track->IsolatedName(); // pobranie nazwy odcinka izolowanego
|
||||||
if (!name.empty()) // jeśli została zwrócona nazwa
|
if( !name.empty() ) // jeśli została zwrócona nazwa
|
||||||
Track->IsolatedEventsAssign(FindEvent(name + ":busy"), FindEvent(name + ":free"));
|
Track->IsolatedEventsAssign(
|
||||||
if (Current->asName.substr(0, 1) ==
|
FindEvent( name + ":busy" ),
|
||||||
"*") // możliwy portal, jeśli nie podłączony od striny 1
|
FindEvent( name + ":free" ) );
|
||||||
|
// możliwy portal, jeśli nie podłączony od striny 1
|
||||||
|
if (Current->asName.substr(0, 1) == "*")
|
||||||
if (!Track->CurrentPrev() && Track->CurrentNext())
|
if (!Track->CurrentPrev() && Track->CurrentNext())
|
||||||
Track->iCategoryFlag |= 0x100; // ustawienie flagi portalu
|
Track->iCategoryFlag |= 0x100; // ustawienie flagi portalu
|
||||||
}
|
}
|
||||||
@@ -2631,7 +2597,7 @@ void TGround::InitTracks()
|
|||||||
Current = new TGroundNode(); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
Current = new TGroundNode(); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
||||||
// Current->asName=p->asName; //mazwa identyczna, jak nazwa odcinka izolowanego
|
// Current->asName=p->asName; //mazwa identyczna, jak nazwa odcinka izolowanego
|
||||||
Current->MemCell = new TMemCell(NULL); // nowa komórka
|
Current->MemCell = new TMemCell(NULL); // nowa komórka
|
||||||
m_trackmap.Add( TP_MEMCELL, p->asName, Current );
|
m_nodemap.Add( TP_MEMCELL, p->asName, Current );
|
||||||
Current->nNext =
|
Current->nNext =
|
||||||
nRootOfType[TP_MEMCELL]; // to nie powinno tutaj być, bo robi się śmietnik
|
nRootOfType[TP_MEMCELL]; // to nie powinno tutaj być, bo robi się śmietnik
|
||||||
nRootOfType[TP_MEMCELL] = Current;
|
nRootOfType[TP_MEMCELL] = Current;
|
||||||
@@ -2639,9 +2605,6 @@ void TGround::InitTracks()
|
|||||||
}
|
}
|
||||||
p = p->Next();
|
p = p->Next();
|
||||||
}
|
}
|
||||||
// for (Current=nRootOfType[TP_TRACK];Current;Current=Current->nNext)
|
|
||||||
// if (Current->pTrack->eType==tt_Cross)
|
|
||||||
// Current->pTrack->ConnectionsLog(); //zalogowanie informacji o połączeniach
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGround::InitTraction()
|
void TGround::InitTraction()
|
||||||
@@ -2849,7 +2812,7 @@ void TGround::InitTraction()
|
|||||||
}
|
}
|
||||||
delete[] nEnds; // nie potrzebne już
|
delete[] nEnds; // nie potrzebne już
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
void TGround::TrackJoin(TGroundNode *Current)
|
void TGround::TrackJoin(TGroundNode *Current)
|
||||||
{ // wyszukiwanie sąsiednich torów do podłączenia (wydzielone na użytek obrotnicy)
|
{ // wyszukiwanie sąsiednich torów do podłączenia (wydzielone na użytek obrotnicy)
|
||||||
TTrack *Track = Current->pTrack;
|
TTrack *Track = Current->pTrack;
|
||||||
@@ -2903,13 +2866,13 @@ bool TGround::InitLaunchers()
|
|||||||
MessageBox(0, "Cannot find Memory Cell for Event Launcher", "Error", MB_OK);
|
MessageBox(0, "Cannot find Memory Cell for Event Launcher", "Error", MB_OK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
EventLauncher->MemCell = NULL;
|
EventLauncher->MemCell = nullptr;
|
||||||
EventLauncher->Event1 = (EventLauncher->asEvent1Name != "none") ?
|
EventLauncher->Event1 = ( EventLauncher->asEvent1Name != "none") ?
|
||||||
FindEvent(EventLauncher->asEvent1Name) :
|
simulation::Events.FindEvent(EventLauncher->asEvent1Name) :
|
||||||
NULL;
|
nullptr;
|
||||||
EventLauncher->Event2 = (EventLauncher->asEvent2Name != "none") ?
|
EventLauncher->Event2 = ( EventLauncher->asEvent2Name != "none") ?
|
||||||
FindEvent(EventLauncher->asEvent2Name) :
|
simulation::Events.FindEvent(EventLauncher->asEvent2Name) :
|
||||||
NULL;
|
nullptr;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3039,6 +3002,7 @@ TTraction * TGround::TractionNearestFind(glm::dvec3 &p, int dir, TGroundNode *n)
|
|||||||
return (nBest ? nBest->hvTraction : nullptr);
|
return (nBest ? nBest->hvTraction : nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
bool TGround::AddToQuery(TEvent *Event, TDynamicObject *Node)
|
bool TGround::AddToQuery(TEvent *Event, TDynamicObject *Node)
|
||||||
{
|
{
|
||||||
if( Event->bEnabled ) {
|
if( Event->bEnabled ) {
|
||||||
@@ -3107,8 +3071,9 @@ bool TGround::AddToQuery(TEvent *Event, TDynamicObject *Node)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TGround::EventConditon(TEvent *e)
|
// sprawdzenie spelnienia warunków dla eventu
|
||||||
{ // sprawdzenie spelnienia warunków dla eventu
|
bool TGround::EventConditon(TEvent *e){
|
||||||
|
|
||||||
if (e->iFlags <= update_only)
|
if (e->iFlags <= update_only)
|
||||||
return true; // bezwarunkowo
|
return true; // bezwarunkowo
|
||||||
|
|
||||||
@@ -3122,56 +3087,51 @@ bool TGround::EventConditon(TEvent *e)
|
|||||||
WriteLog("Random integer: " + std::to_string(rprobability) + " / " + std::to_string(e->Params[10].asdouble));
|
WriteLog("Random integer: " + std::to_string(rprobability) + " / " + std::to_string(e->Params[10].asdouble));
|
||||||
return (e->Params[10].asdouble > rprobability);
|
return (e->Params[10].asdouble > rprobability);
|
||||||
}
|
}
|
||||||
else if (e->iFlags & conditional_memcompare)
|
else if( e->iFlags & conditional_memcompare ) {
|
||||||
{ // porównanie wartości
|
// porównanie wartości
|
||||||
if( nullptr == e->Params[9].asMemCell ) {
|
if( nullptr == e->Params[9].asMemCell ) {
|
||||||
|
|
||||||
ErrorLog( "Event " + e->asName + " trying conditional_memcompare with nonexistent memcell" );
|
ErrorLog( "Event " + e->asName + " trying conditional_memcompare with nonexistent memcell" );
|
||||||
return true; // though this is technically error, we report success to maintain backward compatibility
|
return true; // though this is technically error, we report success to maintain backward compatibility
|
||||||
}
|
}
|
||||||
if (tmpEvent->Params[9].asMemCell->Compare( ( e->Params[ 10 ].asText != nullptr ? e->Params[10].asText : "" ), e->Params[11].asdouble, e->Params[12].asdouble, e->iFlags) ) {
|
auto const comparisonresult =
|
||||||
//logowanie spełnionych warunków
|
tmpEvent->Params[ 9 ].asMemCell->Compare(
|
||||||
LogComment = e->Params[9].asMemCell->Text() + " " +
|
( e->Params[ 10 ].asText != nullptr ?
|
||||||
to_string(e->Params[9].asMemCell->Value1(), 2, 8) + " " +
|
e->Params[ 10 ].asText :
|
||||||
to_string(tmpEvent->Params[9].asMemCell->Value2(), 2, 8) +
|
"" ),
|
||||||
" = ";
|
e->Params[ 11 ].asdouble,
|
||||||
if (TestFlag(e->iFlags, conditional_memstring))
|
e->Params[ 12 ].asdouble,
|
||||||
LogComment += std::string(tmpEvent->Params[10].asText);
|
e->iFlags );
|
||||||
else
|
|
||||||
LogComment += "*";
|
std::string comparisonlog = "Type: MemCompare - ";
|
||||||
if (TestFlag(tmpEvent->iFlags, conditional_memval1))
|
|
||||||
LogComment += " " + to_string(tmpEvent->Params[11].asdouble, 2, 8);
|
comparisonlog +=
|
||||||
else
|
"[" + e->Params[ 9 ].asMemCell->Text() + "]"
|
||||||
LogComment += " *";
|
+ " [" + to_string( e->Params[ 9 ].asMemCell->Value1(), 2 ) + "]"
|
||||||
if (TestFlag(tmpEvent->iFlags, conditional_memval2))
|
+ " [" + to_string( tmpEvent->Params[ 9 ].asMemCell->Value2(), 2 ) + "]";
|
||||||
LogComment += " " + to_string(tmpEvent->Params[12].asdouble, 2, 8);
|
|
||||||
else
|
comparisonlog += (
|
||||||
LogComment += " *";
|
true == comparisonresult ?
|
||||||
WriteLog(LogComment);
|
" == " :
|
||||||
return true;
|
" != " );
|
||||||
}
|
|
||||||
//else if (Global::iWriteLogEnabled && DebugModeFlag) //zawsze bo to bardzo istotne w debugowaniu scenariuszy
|
comparisonlog += (
|
||||||
else
|
TestFlag( e->iFlags, conditional_memstring ) ?
|
||||||
{ // nie zgadza się, więc sprawdzmy, co
|
"[" + std::string( tmpEvent->Params[ 10 ].asText ) + "]" :
|
||||||
LogComment = e->Params[9].asMemCell->Text() + " " +
|
"[*]" );
|
||||||
to_string(e->Params[9].asMemCell->Value1(), 2, 8) + " " +
|
comparisonlog += (
|
||||||
to_string(tmpEvent->Params[9].asMemCell->Value2(), 2, 8) +
|
TestFlag( tmpEvent->iFlags, conditional_memval1 ) ?
|
||||||
" != ";
|
" [" + to_string( tmpEvent->Params[ 11 ].asdouble, 2 ) + "]" :
|
||||||
if (TestFlag(e->iFlags, conditional_memstring))
|
" [*]" );
|
||||||
LogComment += (tmpEvent->Params[10].asText);
|
comparisonlog += (
|
||||||
else
|
TestFlag( tmpEvent->iFlags, conditional_memval2 ) ?
|
||||||
LogComment += "*";
|
" [" + to_string( tmpEvent->Params[ 12 ].asdouble, 2 ) + "]" :
|
||||||
if (TestFlag(tmpEvent->iFlags, conditional_memval1))
|
" [*]" );
|
||||||
LogComment += " " + to_string(tmpEvent->Params[11].asdouble, 2, 8);
|
|
||||||
else
|
WriteLog( comparisonlog );
|
||||||
LogComment += " *";
|
return comparisonresult;
|
||||||
if (TestFlag(tmpEvent->iFlags, conditional_memval2))
|
|
||||||
LogComment += " " + to_string(tmpEvent->Params[12].asdouble, 2, 8);
|
|
||||||
else
|
|
||||||
LogComment += " *";
|
|
||||||
WriteLog(LogComment);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// unrecognized request
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3227,16 +3187,16 @@ bool TGround::CheckQuery()
|
|||||||
&tmpEvent->Params[ 4 ].nGroundNode->pCenter );
|
&tmpEvent->Params[ 4 ].nGroundNode->pCenter );
|
||||||
}
|
}
|
||||||
//if (DebugModeFlag)
|
//if (DebugModeFlag)
|
||||||
WriteLog("Type: UpdateValues & Track command - " +
|
WriteLog("Type: UpdateValues & Track command - [" +
|
||||||
tmpEvent->Params[5].asMemCell->Text() + " " +
|
tmpEvent->Params[5].asMemCell->Text() + "] [" +
|
||||||
std::to_string( tmpEvent->Params[ 5 ].asMemCell->Value1() ) + " " +
|
to_string( tmpEvent->Params[ 5 ].asMemCell->Value1(), 2 ) + "] [" +
|
||||||
std::to_string( tmpEvent->Params[ 5 ].asMemCell->Value2() ) );
|
to_string( tmpEvent->Params[ 5 ].asMemCell->Value2(), 2 ) + "]" );
|
||||||
}
|
}
|
||||||
else //if (DebugModeFlag)
|
else //if (DebugModeFlag)
|
||||||
WriteLog("Type: UpdateValues - " +
|
WriteLog("Type: UpdateValues - [" +
|
||||||
tmpEvent->Params[5].asMemCell->Text() + " " +
|
tmpEvent->Params[5].asMemCell->Text() + "] [" +
|
||||||
std::to_string( tmpEvent->Params[ 5 ].asMemCell->Value1() ) + " " +
|
to_string( tmpEvent->Params[ 5 ].asMemCell->Value1(), 2 ) + "] [" +
|
||||||
std::to_string( tmpEvent->Params[ 5 ].asMemCell->Value2() ) );
|
to_string( tmpEvent->Params[ 5 ].asMemCell->Value2(), 2 ) + "]" );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tp_GetValues:
|
case tp_GetValues:
|
||||||
@@ -3255,24 +3215,26 @@ bool TGround::CheckQuery()
|
|||||||
WriteLog("Type: GetValues");
|
WriteLog("Type: GetValues");
|
||||||
break;
|
break;
|
||||||
case tp_PutValues:
|
case tp_PutValues:
|
||||||
if (tmpEvent->Activator)
|
if (tmpEvent->Activator) {
|
||||||
{
|
// zamiana, bo fizyka ma inaczej niż sceneria
|
||||||
loc.X =
|
loc.X = -tmpEvent->Params[3].asdouble;
|
||||||
-tmpEvent->Params[3].asdouble; // zamiana, bo fizyka ma inaczej niż sceneria
|
|
||||||
loc.Y = tmpEvent->Params[5].asdouble;
|
loc.Y = tmpEvent->Params[5].asdouble;
|
||||||
loc.Z = tmpEvent->Params[4].asdouble;
|
loc.Z = tmpEvent->Params[4].asdouble;
|
||||||
if (tmpEvent->Activator->Mechanik) // przekazanie rozkazu do AI
|
if (tmpEvent->Activator->Mechanik) // przekazanie rozkazu do AI
|
||||||
tmpEvent->Activator->Mechanik->PutCommand(
|
tmpEvent->Activator->Mechanik->PutCommand(
|
||||||
tmpEvent->Params[0].asText, tmpEvent->Params[1].asdouble,
|
tmpEvent->Params[0].asText, tmpEvent->Params[1].asdouble,
|
||||||
tmpEvent->Params[2].asdouble, loc);
|
tmpEvent->Params[2].asdouble, loc);
|
||||||
else
|
else {
|
||||||
{ // przekazanie do pojazdu
|
// przekazanie do pojazdu
|
||||||
tmpEvent->Activator->MoverParameters->PutCommand(
|
tmpEvent->Activator->MoverParameters->PutCommand(
|
||||||
tmpEvent->Params[0].asText, tmpEvent->Params[1].asdouble,
|
tmpEvent->Params[0].asText, tmpEvent->Params[1].asdouble,
|
||||||
tmpEvent->Params[2].asdouble, loc);
|
tmpEvent->Params[2].asdouble, loc);
|
||||||
}
|
}
|
||||||
|
WriteLog("Type: PutValues - [" +
|
||||||
|
std::string(tmpEvent->Params[0].asText) + "] [" +
|
||||||
|
to_string( tmpEvent->Params[ 1 ].asdouble, 2 ) + "] [" +
|
||||||
|
to_string( tmpEvent->Params[ 2 ].asdouble, 2 ) + "]" );
|
||||||
}
|
}
|
||||||
WriteLog("Type: PutValues");
|
|
||||||
break;
|
break;
|
||||||
case tp_Lights:
|
case tp_Lights:
|
||||||
if (tmpEvent->Params[9].asModel)
|
if (tmpEvent->Params[9].asModel)
|
||||||
@@ -3342,11 +3304,10 @@ bool TGround::CheckQuery()
|
|||||||
if (tmpEvent->Params[9].asTrack)
|
if (tmpEvent->Params[9].asTrack)
|
||||||
{ // prędkość na zwrotnicy może być ograniczona z góry we wpisie, większej się nie
|
{ // prędkość na zwrotnicy może być ograniczona z góry we wpisie, większej się nie
|
||||||
// ustawi eventem
|
// ustawi eventem
|
||||||
WriteLog("type: TrackVel");
|
WriteLog("Type: TrackVel");
|
||||||
// WriteLog("Vel: ",tmpEvent->Params[0].asdouble);
|
|
||||||
tmpEvent->Params[9].asTrack->VelocitySet(tmpEvent->Params[0].asdouble);
|
tmpEvent->Params[9].asTrack->VelocitySet(tmpEvent->Params[0].asdouble);
|
||||||
if (DebugModeFlag) // wyświetlana jest ta faktycznie ustawiona
|
if (DebugModeFlag) // wyświetlana jest ta faktycznie ustawiona
|
||||||
WriteLog("vel: ", tmpEvent->Params[9].asTrack->VelocityGet());
|
WriteLog(" - velocity: ", tmpEvent->Params[9].asTrack->VelocityGet());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case tp_DynVel:
|
case tp_DynVel:
|
||||||
@@ -3358,7 +3319,7 @@ bool TGround::CheckQuery()
|
|||||||
if (bCondition || (tmpEvent->iFlags &
|
if (bCondition || (tmpEvent->iFlags &
|
||||||
conditional_anyelse)) // warunek spelniony albo było użyte else
|
conditional_anyelse)) // warunek spelniony albo było użyte else
|
||||||
{
|
{
|
||||||
WriteLog("Multiple passed");
|
WriteLog("Type: Multi-event");
|
||||||
for (i = 0; i < 8; ++i) {
|
for (i = 0; i < 8; ++i) {
|
||||||
// dodawane do kolejki w kolejności zapisania
|
// dodawane do kolejki w kolejności zapisania
|
||||||
if( tmpEvent->Params[ i ].asEvent ) {
|
if( tmpEvent->Params[ i ].asEvent ) {
|
||||||
@@ -3413,7 +3374,7 @@ bool TGround::CheckQuery()
|
|||||||
tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) );
|
tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) );
|
||||||
|
|
||||||
WriteLog(
|
WriteLog(
|
||||||
"whois request (" + to_string( tmpEvent->iFlags ) + ") "
|
"Type: WhoIs (" + to_string( tmpEvent->iFlags ) + ") - "
|
||||||
+ "[name: " + tmpEvent->Activator->MoverParameters->TypeName + "], "
|
+ "[name: " + tmpEvent->Activator->MoverParameters->TypeName + "], "
|
||||||
+ "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], "
|
+ "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], "
|
||||||
+ "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" );
|
+ "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" );
|
||||||
@@ -3427,7 +3388,7 @@ bool TGround::CheckQuery()
|
|||||||
tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) );
|
tmpEvent->iFlags & ( update_memstring | update_memval1 | update_memval2 ) );
|
||||||
|
|
||||||
WriteLog(
|
WriteLog(
|
||||||
"whois request (" + to_string( tmpEvent->iFlags ) + ") "
|
"Type: WhoIs (" + to_string( tmpEvent->iFlags ) + ") - "
|
||||||
+ "[load type: " + tmpEvent->Activator->MoverParameters->LoadType + "], "
|
+ "[load type: " + tmpEvent->Activator->MoverParameters->LoadType + "], "
|
||||||
+ "[current load: " + to_string( tmpEvent->Activator->MoverParameters->Load, 2 ) + "], "
|
+ "[current load: " + to_string( tmpEvent->Activator->MoverParameters->Load, 2 ) + "], "
|
||||||
+ "[max load: " + to_string( tmpEvent->Activator->MoverParameters->MaxLoad, 2 ) + "]" );
|
+ "[max load: " + to_string( tmpEvent->Activator->MoverParameters->MaxLoad, 2 ) + "]" );
|
||||||
@@ -3442,7 +3403,7 @@ bool TGround::CheckQuery()
|
|||||||
tmpEvent->iFlags & (update_memstring | update_memval1 | update_memval2));
|
tmpEvent->iFlags & (update_memstring | update_memval1 | update_memval2));
|
||||||
|
|
||||||
WriteLog(
|
WriteLog(
|
||||||
"whois request (" + to_string( tmpEvent->iFlags ) + ") "
|
"Type: WhoIs (" + to_string( tmpEvent->iFlags ) + ") - "
|
||||||
+ "[destination: " + tmpEvent->Activator->asDestination + "], "
|
+ "[destination: " + tmpEvent->Activator->asDestination + "], "
|
||||||
+ "[direction: " + to_string( tmpEvent->Activator->DirectionGet() ) + "], "
|
+ "[direction: " + to_string( tmpEvent->Activator->DirectionGet() ) + "], "
|
||||||
+ "[engine power: " + to_string( tmpEvent->Activator->MoverParameters->Power, 2 ) + "]" );
|
+ "[engine power: " + to_string( tmpEvent->Activator->MoverParameters->Power, 2 ) + "]" );
|
||||||
@@ -3476,12 +3437,12 @@ bool TGround::CheckQuery()
|
|||||||
case tp_Voltage: // zmiana napięcia w zasilaczu (TractionPowerSource)
|
case tp_Voltage: // zmiana napięcia w zasilaczu (TractionPowerSource)
|
||||||
if (tmpEvent->Params[9].psPower)
|
if (tmpEvent->Params[9].psPower)
|
||||||
{ // na razie takie chamskie ustawienie napięcia zasilania
|
{ // na razie takie chamskie ustawienie napięcia zasilania
|
||||||
WriteLog("type: Voltage");
|
WriteLog("Type: Voltage");
|
||||||
tmpEvent->Params[9].psPower->VoltageSet(tmpEvent->Params[0].asdouble);
|
tmpEvent->Params[9].psPower->VoltageSet(tmpEvent->Params[0].asdouble);
|
||||||
}
|
}
|
||||||
case tp_Friction: // zmiana tarcia na scenerii
|
case tp_Friction: // zmiana tarcia na scenerii
|
||||||
{ // na razie takie chamskie ustawienie napięcia zasilania
|
{ // na razie takie chamskie ustawienie napięcia zasilania
|
||||||
WriteLog("type: Friction");
|
WriteLog("Type: Friction");
|
||||||
Global::fFriction = (tmpEvent->Params[0].asdouble);
|
Global::fFriction = (tmpEvent->Params[0].asdouble);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3492,6 +3453,7 @@ bool TGround::CheckQuery()
|
|||||||
} // while
|
} // while
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void TGround::UpdatePhys(double dt, int iter)
|
void TGround::UpdatePhys(double dt, int iter)
|
||||||
{ // aktualizacja fizyki stałym krokiem: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń
|
{ // aktualizacja fizyki stałym krokiem: dt=krok czasu [s], dt*iter=czas od ostatnich przeliczeń
|
||||||
@@ -3574,13 +3536,6 @@ bool TGround::Update(double dt, int iter)
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// updates scene lights array
|
|
||||||
void
|
|
||||||
TGround::Update_Lights() {
|
|
||||||
|
|
||||||
m_lights.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TGround::Update_Hidden() {
|
TGround::Update_Hidden() {
|
||||||
|
|
||||||
@@ -4179,7 +4134,7 @@ void TGround::DynamicRemove(TDynamicObject *dyn)
|
|||||||
(*n) = node->nNext; // pominięcie na liście
|
(*n) = node->nNext; // pominięcie na liście
|
||||||
Global::TrainDelete(d);
|
Global::TrainDelete(d);
|
||||||
// remove potential entries in the light array
|
// remove potential entries in the light array
|
||||||
m_lights.remove( d );
|
simulation::Lights.remove( d );
|
||||||
d = d->Next(); // przejście do kolejnego pojazdu, póki jeszcze jest
|
d = d->Next(); // przejście do kolejnego pojazdu, póki jeszcze jest
|
||||||
delete node; // usuwanie fizyczne z pamięci
|
delete node; // usuwanie fizyczne z pamięci
|
||||||
}
|
}
|
||||||
|
|||||||
51
Ground.h
51
Ground.h
@@ -10,16 +10,13 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "GL/glew.h"
|
|
||||||
#include "openglgeometrybank.h"
|
|
||||||
#include "VBO.h"
|
|
||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
#include "ResourceManager.h"
|
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
#include "Float3d.h"
|
|
||||||
#include "Names.h"
|
#include "Names.h"
|
||||||
#include "lightarray.h"
|
#include "lightarray.h"
|
||||||
|
#include "simulation.h"
|
||||||
|
|
||||||
typedef int TGroundNodeType;
|
typedef int TGroundNodeType;
|
||||||
// Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie
|
// Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie
|
||||||
@@ -97,7 +94,7 @@ struct TGroundVertex
|
|||||||
// ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node
|
// ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node
|
||||||
struct piece_node {
|
struct piece_node {
|
||||||
std::vector<TGroundVertex> vertices;
|
std::vector<TGroundVertex> vertices;
|
||||||
geometry_handle geometry { 0,0 }; // geometry prepared for drawing
|
geometry_handle geometry { 0, 0 }; // geometry prepared for drawing
|
||||||
};
|
};
|
||||||
|
|
||||||
// obiekt scenerii
|
// obiekt scenerii
|
||||||
@@ -142,9 +139,9 @@ public:
|
|||||||
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
|
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
|
||||||
material_handle m_material; // główna (jedna) tekstura obiektu
|
material_handle m_material; // główna (jedna) tekstura obiektu
|
||||||
glm::vec3
|
glm::vec3
|
||||||
Ambient{ 1.0f, 1.0f, 1.0f },
|
Ambient{ 0.2f },
|
||||||
Diffuse{ 1.0f, 1.0f, 1.0f },
|
Diffuse{ 1.0f },
|
||||||
Specular{ 1.0f, 1.0f, 1.0f }; // oświetlenie
|
Specular{ 0.0f }; // oświetlenie
|
||||||
double fLineThickness; // McZapkie-120702: grubosc linii
|
double fLineThickness; // McZapkie-120702: grubosc linii
|
||||||
bool bVisible;
|
bool bVisible;
|
||||||
|
|
||||||
@@ -155,17 +152,17 @@ public:
|
|||||||
void InitNormals();
|
void InitNormals();
|
||||||
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
|
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
struct bounding_area {
|
struct bounding_area {
|
||||||
|
|
||||||
glm::vec3 center; // mid point of the rectangle
|
glm::vec3 center; // mid point of the rectangle
|
||||||
float radius { 0.0f }; // radius of the bounding sphere
|
float radius { 0.0f }; // radius of the bounding sphere
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
class TSubRect : /*public Resource,*/ public CMesh
|
class TSubRect : /*public Resource,*/ public CMesh
|
||||||
{ // sektor składowy kwadratu kilometrowego
|
{ // sektor składowy kwadratu kilometrowego
|
||||||
public:
|
public:
|
||||||
bounding_area m_area;
|
scene::bounding_area m_area;
|
||||||
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
unsigned int m_framestamp { 0 }; // id of last rendered gfx frame
|
||||||
int iTracks = 0; // ilość torów w (tTracks)
|
int iTracks = 0; // ilość torów w (tTracks)
|
||||||
TTrack **tTracks = nullptr; // tory do renderowania pojazdów
|
TTrack **tTracks = nullptr; // tory do renderowania pojazdów
|
||||||
@@ -219,6 +216,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
virtual ~TGroundRect();
|
virtual ~TGroundRect();
|
||||||
// pobranie wskaźnika do małego kwadratu, utworzenie jeśli trzeba
|
// pobranie wskaźnika do małego kwadratu, utworzenie jeśli trzeba
|
||||||
|
inline
|
||||||
TSubRect * SafeGetSubRect(int iCol, int iRow) {
|
TSubRect * SafeGetSubRect(int iCol, int iRow) {
|
||||||
if( !pSubRects ) {
|
if( !pSubRects ) {
|
||||||
// utworzenie małych kwadratów
|
// utworzenie małych kwadratów
|
||||||
@@ -227,6 +225,7 @@ public:
|
|||||||
return pSubRects + iRow * iNumSubRects + iCol; // zwrócenie właściwego
|
return pSubRects + iRow * iNumSubRects + iCol; // zwrócenie właściwego
|
||||||
};
|
};
|
||||||
// pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
|
// pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
|
||||||
|
inline
|
||||||
TSubRect *FastGetSubRect(int iCol, int iRow) const {
|
TSubRect *FastGetSubRect(int iCol, int iRow) const {
|
||||||
return (
|
return (
|
||||||
pSubRects ?
|
pSubRects ?
|
||||||
@@ -234,8 +233,9 @@ public:
|
|||||||
nullptr); };
|
nullptr); };
|
||||||
void NodeAdd( TGroundNode *Node ); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
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
|
// compares two provided nodes, returns true if their content can be merged
|
||||||
bool mergeable( TGroundNode const &Left, TGroundNode const &Right );
|
bool mergeable( TGroundNode const &Left, TGroundNode const &Right ) const;
|
||||||
// optymalizacja obiektów w sektorach
|
// optymalizacja obiektów w sektorach
|
||||||
|
inline
|
||||||
void Optimize() {
|
void Optimize() {
|
||||||
if( pSubRects ) {
|
if( pSubRects ) {
|
||||||
for( int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i ) {
|
for( int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i ) {
|
||||||
@@ -253,20 +253,23 @@ class TGround
|
|||||||
TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe)
|
TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe)
|
||||||
TGroundNode *nRootDynamic = nullptr; // lista pojazdów
|
TGroundNode *nRootDynamic = nullptr; // lista pojazdów
|
||||||
TGroundNode *nRootOfType[ TP_LAST ]; // tablica grupująca obiekty, przyspiesza szukanie
|
TGroundNode *nRootOfType[ TP_LAST ]; // tablica grupująca obiekty, przyspiesza szukanie
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
TEvent *RootEvent = nullptr; // lista zdarzeń
|
TEvent *RootEvent = nullptr; // lista zdarzeń
|
||||||
TEvent *QueryRootEvent = nullptr,
|
TEvent *QueryRootEvent = nullptr,
|
||||||
*tmpEvent = nullptr;
|
*tmpEvent = nullptr;
|
||||||
typedef std::unordered_map<std::string, TEvent *> event_map;
|
typedef std::unordered_map<std::string, TEvent *> event_map;
|
||||||
event_map m_eventmap;
|
event_map m_eventmap;
|
||||||
TNames<TGroundNode *> m_trackmap;
|
#endif
|
||||||
light_array m_lights; // collection of dynamic light sources present in the scene
|
TNames<TGroundNode *> m_nodemap;
|
||||||
|
|
||||||
vector3 pOrigin;
|
vector3 pOrigin;
|
||||||
vector3 aRotate;
|
vector3 aRotate;
|
||||||
bool bInitDone = false;
|
bool bInitDone = false;
|
||||||
|
|
||||||
private: // metody prywatne
|
private: // metody prywatne
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
bool EventConditon(TEvent *e);
|
bool EventConditon(TEvent *e);
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool bDynamicRemove = false; // czy uruchomić procedurę usuwania pojazdów
|
bool bDynamicRemove = false; // czy uruchomić procedurę usuwania pojazdów
|
||||||
@@ -276,9 +279,11 @@ class TGround
|
|||||||
void Free();
|
void Free();
|
||||||
bool Init( std::string File );
|
bool Init( std::string File );
|
||||||
void FirstInit();
|
void FirstInit();
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
void InitTracks();
|
void InitTracks();
|
||||||
void InitTraction();
|
void InitTraction();
|
||||||
bool InitEvents();
|
bool InitEvents();
|
||||||
|
#endif
|
||||||
bool InitLaunchers();
|
bool InitLaunchers();
|
||||||
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
|
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
|
||||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TGroundNode *Exclude);
|
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TGroundNode *Exclude);
|
||||||
@@ -286,15 +291,16 @@ class TGround
|
|||||||
TGroundNode * AddGroundNode(cParser *parser);
|
TGroundNode * AddGroundNode(cParser *parser);
|
||||||
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
|
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
|
||||||
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS
|
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
|
void Update_Hidden(); // updates invisible elements of the scene
|
||||||
bool AddToQuery(TEvent *Event, TDynamicObject *Node);
|
|
||||||
bool GetTraction(TDynamicObject *model);
|
bool GetTraction(TDynamicObject *model);
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
bool AddToQuery( TEvent *Event, TDynamicObject *Node );
|
||||||
bool CheckQuery();
|
bool CheckQuery();
|
||||||
|
#endif
|
||||||
TGroundNode * DynamicFindAny(std::string const &Name);
|
TGroundNode * DynamicFindAny(std::string const &Name);
|
||||||
TGroundNode * DynamicFind(std::string const &Name);
|
TGroundNode * DynamicFind(std::string const &Name);
|
||||||
void DynamicList(bool all = false);
|
void DynamicList(bool all = false);
|
||||||
TGroundNode * FindGroundNode(std::string asNameToFind, TGroundNodeType iNodeType);
|
TGroundNode * FindGroundNode(std::string const &asNameToFind, TGroundNodeType const iNodeType);
|
||||||
TGroundRect * GetRect( double x, double z );
|
TGroundRect * GetRect( double x, double z );
|
||||||
TSubRect * GetSubRect( int iCol, int iRow );
|
TSubRect * GetSubRect( int iCol, int iRow );
|
||||||
inline
|
inline
|
||||||
@@ -310,8 +316,9 @@ class TGround
|
|||||||
inline
|
inline
|
||||||
int GetColFromX(double x) {
|
int GetColFromX(double x) {
|
||||||
return (int)(x / fSubRectSize + fHalfTotalNumSubRects); };
|
return (int)(x / fSubRectSize + fHalfTotalNumSubRects); };
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
TEvent * FindEvent(const std::string &asEventName);
|
TEvent * FindEvent(const std::string &asEventName);
|
||||||
TEvent * FindEventScan(const std::string &asEventName);
|
#endif
|
||||||
void TrackJoin(TGroundNode *Current);
|
void TrackJoin(TGroundNode *Current);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -330,10 +337,8 @@ class TGround
|
|||||||
void WyslijUszkodzenia(const std::string &t, char fl);
|
void WyslijUszkodzenia(const std::string &t, char fl);
|
||||||
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
||||||
void RadioStop(vector3 pPosition);
|
void RadioStop(vector3 pPosition);
|
||||||
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0,
|
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
|
||||||
bool mech = false);
|
TDynamicObject * CouplerNearest(vector3 pPosition, double distance = 20.0, bool mech = false);
|
||||||
TDynamicObject * CouplerNearest(vector3 pPosition, double distance = 20.0,
|
|
||||||
bool mech = false);
|
|
||||||
void DynamicRemove(TDynamicObject *dyn);
|
void DynamicRemove(TDynamicObject *dyn);
|
||||||
void TerrainRead(std::string const &f);
|
void TerrainRead(std::string const &f);
|
||||||
void TerrainWrite();
|
void TerrainWrite();
|
||||||
|
|||||||
29
MemCell.cpp
29
MemCell.cpp
@@ -25,17 +25,18 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// legacy constructor
|
||||||
TMemCell::TMemCell(vector3 *p)
|
TMemCell::TMemCell(vector3 *p)
|
||||||
{
|
{
|
||||||
fValue1 = fValue2 = 0;
|
fValue1 = fValue2 = 0;
|
||||||
vPosition =
|
m_location =
|
||||||
p ? *p : vector3(0, 0, 0); // ustawienie współrzędnych, bo do TGroundNode nie ma dostępu
|
p ? *p : glm::dvec3(); // 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 +104,17 @@ 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
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
*parser >> szText;
|
parser->getTokens( 3, false );
|
||||||
parser->getTokens( 2, false );
|
|
||||||
*parser
|
*parser
|
||||||
|
#else
|
||||||
|
parser->getTokens( 6, false );
|
||||||
|
*parser
|
||||||
|
>> m_location.x
|
||||||
|
>> m_location.y
|
||||||
|
>> m_location.z
|
||||||
|
#endif
|
||||||
|
>> szText
|
||||||
>> fValue1
|
>> fValue1
|
||||||
>> fValue2;
|
>> fValue2;
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
@@ -150,11 +158,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)
|
||||||
|
|||||||
77
MemCell.h
77
MemCell.h
@@ -10,52 +10,59 @@ 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:
|
private:
|
||||||
Math3D::vector3 vPosition;
|
// content
|
||||||
std::string szText;
|
std::string szText;
|
||||||
double fValue1;
|
double fValue1 { 0.0 };
|
||||||
double fValue2;
|
double fValue2 { 0.0 };
|
||||||
TCommandType eCommand;
|
// other
|
||||||
bool bCommand; // czy zawiera komendę dla zatrzymanego AI
|
TCommandType eCommand { cm_Unknown };
|
||||||
TEvent *OnSent; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład
|
bool bCommand { false }; // czy zawiera komendę dla zatrzymanego AI
|
||||||
|
TEvent *OnSent { nullptr }; // 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, Math3D::vector3 *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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class memory_manager : public basic_table<TMemCell> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
20
Model3d.cpp
20
Model3d.cpp
@@ -1023,7 +1023,7 @@ TSubModel::convert( TGroundNode &Groundnode ) const {
|
|||||||
|
|
||||||
if( m_geometry == null_handle ) { return; }
|
if( m_geometry == null_handle ) { return; }
|
||||||
|
|
||||||
std::size_t vertexcount { 0 };
|
int vertexcount { 0 };
|
||||||
std::vector<TGroundVertex> importedvertices;
|
std::vector<TGroundVertex> importedvertices;
|
||||||
TGroundVertex vertex, vertex1, vertex2;
|
TGroundVertex vertex, vertex1, vertex2;
|
||||||
for( auto const &sourcevertex : GfxRenderer.Vertices( m_geometry ) ) {
|
for( auto const &sourcevertex : GfxRenderer.Vertices( m_geometry ) ) {
|
||||||
@@ -1038,31 +1038,29 @@ TSubModel::convert( TGroundNode &Groundnode ) const {
|
|||||||
importedvertices.emplace_back( vertex2 );
|
importedvertices.emplace_back( vertex2 );
|
||||||
importedvertices.emplace_back( vertex );
|
importedvertices.emplace_back( vertex );
|
||||||
}
|
}
|
||||||
|
// start a new triangle
|
||||||
|
vertexcount = -1;
|
||||||
}
|
}
|
||||||
++vertexcount;
|
++vertexcount;
|
||||||
if( vertexcount > 2 ) { vertexcount = 0; } // start new triangle if needed
|
|
||||||
}
|
}
|
||||||
if( Groundnode.Piece == nullptr ) {
|
if( Groundnode.Piece == nullptr ) {
|
||||||
Groundnode.Piece = new piece_node();
|
Groundnode.Piece = new piece_node();
|
||||||
}
|
}
|
||||||
Groundnode.iNumVerts = importedvertices.size();
|
Groundnode.iNumVerts = importedvertices.size();
|
||||||
if( Groundnode.iNumVerts > 0 ) {
|
if( Groundnode.iNumVerts > 0 ) {
|
||||||
|
// assign imported geometry to the node...
|
||||||
Groundnode.Piece->vertices.swap( importedvertices );
|
Groundnode.Piece->vertices.swap( importedvertices );
|
||||||
|
// ...and calculate center...
|
||||||
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
||||||
Groundnode.pCenter += vertex.position;
|
Groundnode.pCenter += vertex.position;
|
||||||
}
|
}
|
||||||
Groundnode.pCenter /= Groundnode.iNumVerts;
|
Groundnode.pCenter /= Groundnode.iNumVerts;
|
||||||
|
// ...and bounding area
|
||||||
double r { 0.0 };
|
double squareradius { 0.0 };
|
||||||
double tf;
|
|
||||||
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
||||||
tf = glm::length2( vertex.position - glm::dvec3{ Groundnode.pCenter } );
|
squareradius = std::max( squareradius, glm::length2( vertex.position - glm::dvec3{ Groundnode.pCenter } ) );
|
||||||
if( tf > r )
|
|
||||||
r = tf;
|
|
||||||
}
|
}
|
||||||
Groundnode.fSquareRadius += r;
|
Groundnode.fSquareRadius += squareradius;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
Names.h
44
Names.h
@@ -65,3 +65,47 @@ private:
|
|||||||
// members:
|
// members:
|
||||||
typemap_map m_maps; // list of object maps of types specified so far
|
typemap_map m_maps; // list of object maps of types specified so far
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Type_>
|
||||||
|
class basic_table {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// destructor
|
||||||
|
~basic_table() {
|
||||||
|
for( auto *item : m_items ) {
|
||||||
|
delete item; } }
|
||||||
|
// methods
|
||||||
|
// adds provided item to the collection. returns: true if there's no duplicate with the same name, false otherwise
|
||||||
|
bool
|
||||||
|
insert( Type_ *Item ) {
|
||||||
|
m_items.emplace_back( Item );
|
||||||
|
auto const itemname = Item->name();
|
||||||
|
if( ( true == itemname.empty() ) || ( itemname == "none" ) ) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
// cell with this name already exists; update mapping to point to the new one, for backward compatibility
|
||||||
|
mapping.first->second = itemhandle;
|
||||||
|
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 ); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// types
|
||||||
|
using type_sequence = std::deque<Type_ *>;
|
||||||
|
using type_map = std::unordered_map<std::string, std::size_t>;
|
||||||
|
// members
|
||||||
|
type_sequence m_items;
|
||||||
|
type_map m_itemmap;
|
||||||
|
};
|
||||||
|
|||||||
415
Track.cpp
415
Track.cpp
@@ -139,13 +139,12 @@ void TIsolated::Modify(int i, TDynamicObject *o)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// tworzenie nowego odcinka ruchu
|
// tworzenie nowego odcinka ruchu
|
||||||
TTrack::TTrack(TGroundNode *g) :
|
TTrack::TTrack( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||||
pMyNode( g ) // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
|
|
||||||
{
|
// legacy constructor
|
||||||
fRadiusTable[ 0 ] = 0.0;
|
TTrack::TTrack( std::string Name ) {
|
||||||
fRadiusTable[ 1 ] = 0.0;
|
|
||||||
nFouling[ 0 ] = nullptr;
|
m_name = Name;
|
||||||
nFouling[ 1 ] = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TTrack::~TTrack()
|
TTrack::~TTrack()
|
||||||
@@ -182,7 +181,7 @@ TTrack * TTrack::Create400m(int what, double dx)
|
|||||||
{ // tworzenie toru do wstawiania taboru podczas konwersji na E3D
|
{ // tworzenie toru do wstawiania taboru podczas konwersji na E3D
|
||||||
TGroundNode *tmp = new TGroundNode(TP_TRACK); // node
|
TGroundNode *tmp = new TGroundNode(TP_TRACK); // node
|
||||||
TTrack *trk = tmp->pTrack;
|
TTrack *trk = tmp->pTrack;
|
||||||
trk->bVisible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
|
trk->m_visible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
|
||||||
trk->iCategoryFlag = what; // taki sam typ plus informacja, że dodatkowy
|
trk->iCategoryFlag = what; // taki sam typ plus informacja, że dodatkowy
|
||||||
trk->Init(); // utworzenie segmentu
|
trk->Init(); // utworzenie segmentu
|
||||||
trk->Segment->Init(vector3(-dx, 0, 0), vector3(-dx, 0, 400), 10.0, 0, 0); // prosty
|
trk->Segment->Init(vector3(-dx, 0, 0), vector3(-dx, 0, 400), 10.0, 0, 0); // prosty
|
||||||
@@ -195,12 +194,10 @@ TTrack * TTrack::Create400m(int what, double dx)
|
|||||||
|
|
||||||
TTrack * TTrack::NullCreate(int dir)
|
TTrack * TTrack::NullCreate(int dir)
|
||||||
{ // tworzenie toru wykolejającego od strony (dir), albo pętli dla samochodów
|
{ // tworzenie toru wykolejającego od strony (dir), albo pętli dla samochodów
|
||||||
TGroundNode *tmp = new TGroundNode(TP_TRACK), *tmp2 = NULL; // node
|
TGroundNode *tmp = new TGroundNode( TP_TRACK );
|
||||||
|
TGroundNode *tmp2 = nullptr; // node
|
||||||
TTrack *trk = tmp->pTrack; // tor; UWAGA! obrotnica może generować duże ilości tego
|
TTrack *trk = tmp->pTrack; // tor; UWAGA! obrotnica może generować duże ilości tego
|
||||||
// tmp->iType=TP_TRACK;
|
trk->m_visible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
|
||||||
// TTrack* trk=new TTrack(tmp); //tor; UWAGA! obrotnica może generować duże ilości tego
|
|
||||||
// tmp->pTrack=trk;
|
|
||||||
trk->bVisible = false; // nie potrzeba pokazywać, zresztą i tak nie ma tekstur
|
|
||||||
// trk->iTrapezoid=1; //są przechyłki do uwzględniania w rysowaniu
|
// trk->iTrapezoid=1; //są przechyłki do uwzględniania w rysowaniu
|
||||||
trk->iCategoryFlag = (iCategoryFlag & 15) | 0x80; // taki sam typ plus informacja, że dodatkowy
|
trk->iCategoryFlag = (iCategoryFlag & 15) | 0x80; // taki sam typ plus informacja, że dodatkowy
|
||||||
float r1, r2;
|
float r1, r2;
|
||||||
@@ -216,25 +213,21 @@ TTrack * TTrack::NullCreate(int dir)
|
|||||||
case 0:
|
case 0:
|
||||||
p1 = Segment->FastGetPoint_0();
|
p1 = Segment->FastGetPoint_0();
|
||||||
p2 = p1 - 450.0 * Normalize(Segment->GetDirection1());
|
p2 = p1 - 450.0 * Normalize(Segment->GetDirection1());
|
||||||
trk->Segment->Init(p1, p2, 5, -RadToDeg(r1),
|
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||||
70.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
|
trk->Segment->Init(p1, p2, 5, -RadToDeg(r1), 70.0);
|
||||||
ConnectPrevPrev(trk, 0);
|
ConnectPrevPrev(trk, 0);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
p1 = Segment->FastGetPoint_1();
|
p1 = Segment->FastGetPoint_1();
|
||||||
p2 = p1 - 450.0 * Normalize(Segment->GetDirection2());
|
p2 = p1 - 450.0 * Normalize(Segment->GetDirection2());
|
||||||
trk->Segment->Init(p1, p2, 5, RadToDeg(r2),
|
// bo prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||||
70.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
|
trk->Segment->Init(p1, p2, 5, RadToDeg(r2), 70.0);
|
||||||
ConnectNextPrev(trk, 0);
|
ConnectNextPrev(trk, 0);
|
||||||
break;
|
break;
|
||||||
case 3: // na razie nie możliwe
|
case 3: // na razie nie możliwe
|
||||||
p1 = SwitchExtension->Segments[1]->FastGetPoint_1(); // koniec toru drugiego zwrotnicy
|
p1 = SwitchExtension->Segments[1]->FastGetPoint_1(); // koniec toru drugiego zwrotnicy
|
||||||
p2 = p1 -
|
p2 = p1 - 450.0 * Normalize( SwitchExtension->Segments[1]->GetDirection2()); // przedłużenie na wprost
|
||||||
450.0 *
|
trk->Segment->Init(p1, p2, 5, RadToDeg(r2), 70.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||||
Normalize(
|
|
||||||
SwitchExtension->Segments[1]->GetDirection2()); // przedłużenie na wprost
|
|
||||||
trk->Segment->Init(p1, p2, 5, RadToDeg(r2),
|
|
||||||
70.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
|
|
||||||
ConnectNextPrev(trk, 0);
|
ConnectNextPrev(trk, 0);
|
||||||
// trk->ConnectPrevNext(trk,dir);
|
// trk->ConnectPrevNext(trk,dir);
|
||||||
SetConnections(1); // skopiowanie połączeń
|
SetConnections(1); // skopiowanie połączeń
|
||||||
@@ -251,13 +244,13 @@ TTrack * TTrack::NullCreate(int dir)
|
|||||||
TTrack *trk2 = tmp2->pTrack;
|
TTrack *trk2 = tmp2->pTrack;
|
||||||
trk2->iCategoryFlag =
|
trk2->iCategoryFlag =
|
||||||
(iCategoryFlag & 15) | 0x80; // taki sam typ plus informacja, że dodatkowy
|
(iCategoryFlag & 15) | 0x80; // taki sam typ plus informacja, że dodatkowy
|
||||||
trk2->bVisible = false;
|
trk2->m_visible = false;
|
||||||
trk2->fVelocity = 20.0; // zawracanie powoli
|
trk2->fVelocity = 20.0; // zawracanie powoli
|
||||||
trk2->fRadius = 20.0; // promień, aby się dodawało do tabelki prędkości i liczyło
|
trk2->fRadius = 20.0; // promień, aby się dodawało do tabelki prędkości i liczyło
|
||||||
// narastająco
|
// narastająco
|
||||||
trk2->Init(); // utworzenie segmentu
|
trk2->Init(); // utworzenie segmentu
|
||||||
trk->pMyNode->asName = pMyNode->asName + ":loopstart";
|
trk->m_name = m_name + ":loopstart";
|
||||||
trk2->pMyNode->asName = pMyNode->asName + ":loopfinish";
|
trk2->m_name = m_name + ":loopfinish";
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{ //łączenie z nowym torem
|
{ //łączenie z nowym torem
|
||||||
case 0:
|
case 0:
|
||||||
@@ -320,8 +313,8 @@ void TTrack::ConnectPrevNext(TTrack *pTrack, int typ)
|
|||||||
iPrevDirection = typ | 1; // 1:zwykły lub pierwszy zwrotnicy, 3:drugi zwrotnicy
|
iPrevDirection = typ | 1; // 1:zwykły lub pierwszy zwrotnicy, 3:drugi zwrotnicy
|
||||||
pTrack->trNext = this;
|
pTrack->trNext = this;
|
||||||
pTrack->iNextDirection = 0;
|
pTrack->iNextDirection = 0;
|
||||||
if (bVisible)
|
if (m_visible)
|
||||||
if (pTrack->bVisible)
|
if (pTrack->m_visible)
|
||||||
if (eType == tt_Normal) // jeśli łączone są dwa normalne
|
if (eType == tt_Normal) // jeśli łączone są dwa normalne
|
||||||
if (pTrack->eType == tt_Normal)
|
if (pTrack->eType == tt_Normal)
|
||||||
if ((fTrackWidth !=
|
if ((fTrackWidth !=
|
||||||
@@ -340,8 +333,8 @@ void TTrack::ConnectNextPrev(TTrack *pTrack, int typ)
|
|||||||
iNextDirection = ((pTrack->eType == tt_Switch) ? 0 : (typ & 2));
|
iNextDirection = ((pTrack->eType == tt_Switch) ? 0 : (typ & 2));
|
||||||
pTrack->trPrev = this;
|
pTrack->trPrev = this;
|
||||||
pTrack->iPrevDirection = 1;
|
pTrack->iPrevDirection = 1;
|
||||||
if (bVisible)
|
if (m_visible)
|
||||||
if (pTrack->bVisible)
|
if (pTrack->m_visible)
|
||||||
if (eType == tt_Normal) // jeśli łączone są dwa normalne
|
if (eType == tt_Normal) // jeśli łączone są dwa normalne
|
||||||
if (pTrack->eType == tt_Normal)
|
if (pTrack->eType == tt_Normal)
|
||||||
if ((fTrackWidth !=
|
if ((fTrackWidth !=
|
||||||
@@ -363,25 +356,15 @@ void TTrack::ConnectNextNext(TTrack *pTrack, int typ)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector3 MakeCPoint(vector3 p, double d, double a1, double a2)
|
|
||||||
{
|
|
||||||
vector3 cp = vector3(0, 0, 1);
|
|
||||||
cp.RotateX(DegToRad(a2));
|
|
||||||
cp.RotateY(DegToRad(a1));
|
|
||||||
cp = cp * d + p;
|
|
||||||
return cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector3 LoadPoint(cParser *parser)
|
vector3 LoadPoint(cParser *parser)
|
||||||
{ // pobranie współrzędnych punktu
|
{ // pobranie współrzędnych punktu
|
||||||
vector3 p;
|
vector3 p;
|
||||||
std::string token;
|
|
||||||
parser->getTokens(3);
|
parser->getTokens(3);
|
||||||
*parser >> p.x >> p.y >> p.z;
|
*parser >> p.x >> p.y >> p.z;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
|
void TTrack::Load(cParser *parser, vector3 pOrigin)
|
||||||
{ // pobranie obiektu trajektorii ruchu
|
{ // pobranie obiektu trajektorii ruchu
|
||||||
vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
|
vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
|
||||||
double a1, a2, r1, r2, r3, r4;
|
double a1, a2, r1, r2, r3, r4;
|
||||||
@@ -464,8 +447,8 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
|
|||||||
}
|
}
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
bVisible = (token.compare("vis") == 0); // visible
|
m_visible = (token.compare("vis") == 0); // visible
|
||||||
if (bVisible)
|
if (m_visible)
|
||||||
{
|
{
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> str; // railtex
|
*parser >> str; // railtex
|
||||||
@@ -718,24 +701,28 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
|
|||||||
}
|
}
|
||||||
else if (str == "angle1")
|
else if (str == "angle1")
|
||||||
{ // kąt ścięcia końca od strony 1
|
{ // kąt ścięcia końca od strony 1
|
||||||
|
// NOTE: not used/implemented
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> a1;
|
*parser >> a1;
|
||||||
Segment->AngleSet(0, a1);
|
//Segment->AngleSet(0, a1);
|
||||||
}
|
}
|
||||||
else if (str == "angle2")
|
else if (str == "angle2")
|
||||||
{ // kąt ścięcia końca od strony 2
|
{ // kąt ścięcia końca od strony 2
|
||||||
|
// NOTE: not used/implemented
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> a2;
|
*parser >> a2;
|
||||||
Segment->AngleSet(1, a2);
|
//Segment->AngleSet(1, a2);
|
||||||
}
|
}
|
||||||
else if (str == "fouling1")
|
else if (str == "fouling1")
|
||||||
{ // wskazanie modelu ukresu w kierunku 1
|
{ // wskazanie modelu ukresu w kierunku 1
|
||||||
|
// NOTE: not used/implemented
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
// nFouling[0]=
|
// nFouling[0]=
|
||||||
}
|
}
|
||||||
else if (str == "fouling2")
|
else if (str == "fouling2")
|
||||||
{ // wskazanie modelu ukresu w kierunku 2
|
{ // wskazanie modelu ukresu w kierunku 2
|
||||||
|
// NOTE: not used/implemented
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
// nFouling[1]=
|
// nFouling[1]=
|
||||||
@@ -749,19 +736,26 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
|
|||||||
// ograniczenie dla pantografujących)
|
// ograniczenie dla pantografujących)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ErrorLog("Unknown property: \"" + str + "\" in track \"" + name + "\"");
|
ErrorLog("Unknown property: \"" + str + "\" in track \"" + m_name + "\"");
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
str = token;
|
str = token;
|
||||||
}
|
}
|
||||||
// alternatywny zapis nazwy odcinka izolowanego - po znaku "@" w nazwie toru
|
// alternatywny zapis nazwy odcinka izolowanego - po znaku "@" w nazwie toru
|
||||||
if (!pIsolated)
|
if (!pIsolated)
|
||||||
if ((i = name.find("@")) != std::string::npos)
|
if ((i = m_name.find("@")) != std::string::npos)
|
||||||
if (i < name.length()) // nie może być puste
|
if (i < m_name.length()) // nie może być puste
|
||||||
{
|
{
|
||||||
pIsolated = TIsolated::Find(name.substr(i + 1, name.length()));
|
pIsolated = TIsolated::Find(m_name.substr(i + 1, m_name.length()));
|
||||||
name = name.substr(0, i - 1); // usunięcie z nazwy
|
m_name = m_name.substr(0, i - 1); // usunięcie z nazwy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate path location
|
||||||
|
m_location = glm::dvec3{ (
|
||||||
|
CurrentSegment()->FastGetPoint_0()
|
||||||
|
+ CurrentSegment()->FastGetPoint( 0.5 )
|
||||||
|
+ CurrentSegment()->FastGetPoint_1() )
|
||||||
|
/ 3.0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: refactor this mess
|
// TODO: refactor this mess
|
||||||
@@ -771,7 +765,7 @@ bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent
|
|||||||
|
|
||||||
if( NewEvent0 == nullptr ) {
|
if( NewEvent0 == nullptr ) {
|
||||||
if( false == asEvent0Name.empty() ) {
|
if( false == asEvent0Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEvent0Name + "\" assigned to track \"" + pMyNode->asName + "\" does not exist" );
|
ErrorLog( "Bad event: event \"" + asEvent0Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,7 +783,7 @@ bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent
|
|||||||
|
|
||||||
if( NewEvent1 == nullptr ) {
|
if( NewEvent1 == nullptr ) {
|
||||||
if( false == asEvent1Name.empty() ) {
|
if( false == asEvent1Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEvent1Name + "\" assigned to track \"" + pMyNode->asName + "\" does not exist" );
|
ErrorLog( "Bad event: event \"" + asEvent1Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -807,7 +801,7 @@ bool TTrack::AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent
|
|||||||
|
|
||||||
if( NewEvent2 == nullptr ) {
|
if( NewEvent2 == nullptr ) {
|
||||||
if( false == asEvent2Name.empty() ) {
|
if( false == asEvent2Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEvent2Name + "\" assigned to track \"" + pMyNode->asName + "\" does not exist" );
|
ErrorLog( "Bad event: event \"" + asEvent2Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -832,7 +826,7 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
|
|||||||
|
|
||||||
if( NewEvent0 == nullptr ) {
|
if( NewEvent0 == nullptr ) {
|
||||||
if( false == asEventall0Name.empty() ) {
|
if( false == asEventall0Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEventall0Name + "\" assigned to track \"" + pMyNode->asName + "\" does not exist" );
|
ErrorLog( "Bad event: event \"" + asEventall0Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -850,7 +844,7 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
|
|||||||
|
|
||||||
if( NewEvent1 == nullptr ) {
|
if( NewEvent1 == nullptr ) {
|
||||||
if( false == asEventall1Name.empty() ) {
|
if( false == asEventall1Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEventall1Name + "\" assigned to track \"" + pMyNode->asName + "\" does not exist" );
|
ErrorLog( "Bad event: event \"" + asEventall1Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -868,7 +862,7 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
|
|||||||
|
|
||||||
if( NewEvent2 == nullptr ) {
|
if( NewEvent2 == nullptr ) {
|
||||||
if( false == asEventall2Name.empty() ) {
|
if( false == asEventall2Name.empty() ) {
|
||||||
ErrorLog( "Bad event: event \"" + asEventall2Name + "\" assigned to track \"" + pMyNode->asName + "\" does not exist" );
|
ErrorLog( "Bad event: event \"" + asEventall2Name + "\" assigned to track \"" + m_name + "\" does not exist" );
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -921,7 +915,7 @@ bool TTrack::IsolatedEventsAssign(TEvent *busy, TEvent *free)
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ABu: przeniesione z Track.h i poprawione!!!
|
// ABu: przeniesione z Path.h i poprawione!!!
|
||||||
bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
|
bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
|
||||||
{ // dodanie pojazdu do trajektorii
|
{ // dodanie pojazdu do trajektorii
|
||||||
// Ra: tymczasowo wysyłanie informacji o zajętości konkretnego toru
|
// Ra: tymczasowo wysyłanie informacji o zajętości konkretnego toru
|
||||||
@@ -935,9 +929,9 @@ bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
|
|||||||
// jeśli multiplayer
|
// jeśli multiplayer
|
||||||
if( true == Dynamics.empty() ) {
|
if( true == Dynamics.empty() ) {
|
||||||
// pierwszy zajmujący
|
// pierwszy zajmujący
|
||||||
if( pMyNode->asName != "none" ) {
|
if( m_name != "none" ) {
|
||||||
// przekazanie informacji o zajętości toru
|
// przekazanie informacji o zajętości toru
|
||||||
Global::pGround->WyslijString( pMyNode->asName, 8 );
|
Global::pGround->WyslijString( m_name, 8 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1027,9 +1021,9 @@ bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic)
|
|||||||
// jeśli multiplayer
|
// jeśli multiplayer
|
||||||
if( true == Dynamics.empty() ) {
|
if( true == Dynamics.empty() ) {
|
||||||
// jeśli już nie ma żadnego
|
// jeśli już nie ma żadnego
|
||||||
if( pMyNode->asName != "none" ) {
|
if( m_name != "none" ) {
|
||||||
// przekazanie informacji o zwolnieniu toru
|
// przekazanie informacji o zwolnieniu toru
|
||||||
Global::pGround->WyslijString( pMyNode->asName, 9 );
|
Global::pGround->WyslijString( m_name, 9 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1079,7 +1073,12 @@ void TTrack::RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joi
|
|||||||
};
|
};
|
||||||
|
|
||||||
// wypełnianie tablic VBO
|
// wypełnianie tablic VBO
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
void TTrack::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ) {
|
||||||
|
#else
|
||||||
void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
||||||
|
#endif
|
||||||
// Ra: trzeba rozdzielić szyny od podsypki, aby móc grupować wg tekstur
|
// Ra: trzeba rozdzielić szyny od podsypki, aby móc grupować wg tekstur
|
||||||
auto const fHTW = 0.5f * std::abs(fTrackWidth);
|
auto const fHTW = 0.5f * std::abs(fTrackWidth);
|
||||||
auto const side = std::abs(fTexWidth); // szerokść podsypki na zewnątrz szyny albo pobocza
|
auto const side = std::abs(fTexWidth); // szerokść podsypki na zewnątrz szyny albo pobocza
|
||||||
@@ -1116,7 +1115,11 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
normal2 = normal1;
|
normal2 = normal1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const origin { pMyNode->m_rootposition };
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
if( Bank != 0 ) {
|
||||||
|
m_origin = Origin;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
float roll1, roll2;
|
float roll1, roll2;
|
||||||
switch (iCategoryFlag & 15)
|
switch (iCategoryFlag & 15)
|
||||||
@@ -1326,7 +1329,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, bpts1, iTrapezoid ? -4 : 4, fTexLength);
|
||||||
if( ( Bank != 0 ) && ( true == Geometry2.empty() ) ) {
|
if( ( Bank != 0 ) && ( true == Geometry2.empty() ) ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
}
|
}
|
||||||
@@ -1339,18 +1342,18 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
{ // szyny - generujemy dwie, najwyżej rysować się będzie jedną
|
{ // szyny - generujemy dwie, najwyżej rysować się będzie jedną
|
||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
if( ( Bank != 0 ) && ( true == Geometry1.empty() ) ) {
|
if( ( Bank != 0 ) && ( true == Geometry1.empty() ) ) {
|
||||||
Segment->RenderLoft( vertices, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear(); // reuse the scratchpad
|
vertices.clear(); // reuse the scratchpad
|
||||||
Segment->RenderLoft( vertices, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
}
|
}
|
||||||
if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) {
|
if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) {
|
||||||
// special variant, replace existing data for a turntable track
|
// special variant, replace existing data for a turntable track
|
||||||
Segment->RenderLoft( vertices, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||||
GfxRenderer.Replace( vertices, Geometry1[ 0 ] );
|
GfxRenderer.Replace( vertices, Geometry1[ 0 ] );
|
||||||
vertices.clear(); // reuse the scratchpad
|
vertices.clear(); // reuse the scratchpad
|
||||||
Segment->RenderLoft( vertices, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||||
GfxRenderer.Replace( vertices, Geometry1[ 1 ] );
|
GfxRenderer.Replace( vertices, Geometry1[ 1 ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1392,27 +1395,27 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
if( m_material1 ) {
|
if( m_material1 ) {
|
||||||
// fixed parts
|
// fixed parts
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength, 1.0, 2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength, 1.0, 2 );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( m_material2 ) {
|
if( m_material2 ) {
|
||||||
// fixed parts
|
// fixed parts
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength, 1.0, 2 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength, 1.0, 2 );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -1422,27 +1425,27 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
if( m_material1 ) {
|
if( m_material1 ) {
|
||||||
// fixed parts
|
// fixed parts
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( m_material2 ) {
|
if( m_material2 ) {
|
||||||
// fixed parts
|
// fixed parts
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -1501,7 +1504,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
if (m_material1) // jeśli podana była tekstura, generujemy trójkąty
|
if (m_material1) // jeśli podana była tekstura, generujemy trójkąty
|
||||||
{ // tworzenie trójkątów nawierzchni szosy
|
{ // tworzenie trójkątów nawierzchni szosy
|
||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
}
|
}
|
||||||
if (m_material2)
|
if (m_material2)
|
||||||
@@ -1665,24 +1668,24 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony
|
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony
|
||||||
// odcinka
|
// odcinka
|
||||||
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
||||||
Segment->RenderLoft( vertices, origin, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej
|
Segment->RenderLoft( vertices, m_origin, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||||
Segment->RenderLoft( vertices, origin, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej
|
Segment->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // pobocza zwykłe, brak przechyłki
|
else { // pobocza zwykłe, brak przechyłki
|
||||||
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
||||||
Segment->RenderLoft( vertices, origin, rpts1, 3, fTexLength );
|
Segment->RenderLoft( vertices, m_origin, rpts1, 3, fTexLength );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||||
Segment->RenderLoft( vertices, origin, rpts2, 3, fTexLength );
|
Segment->RenderLoft( vertices, m_origin, rpts2, 3, fTexLength );
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -1915,22 +1918,22 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
if (SwitchExtension->iRoads == 4)
|
if (SwitchExtension->iRoads == 4)
|
||||||
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka
|
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka
|
||||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||||
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
SwitchExtension->Segments[ 3 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
SwitchExtension->Segments[ 3 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
SwitchExtension->Segments[ 4 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
SwitchExtension->Segments[ 4 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
SwitchExtension->Segments[ 5 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
SwitchExtension->Segments[ 5 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
@@ -1940,17 +1943,17 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
else {
|
else {
|
||||||
// punkt 3 pokrywa się z punktem 1, jak w zwrotnicy; połączenie 1->2 nie musi być prostoliniowe
|
// punkt 3 pokrywa się z punktem 1, jak w zwrotnicy; połączenie 1->2 nie musi być prostoliniowe
|
||||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||||
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4
|
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony)
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony)
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2
|
||||||
if( true == render ) {
|
if( true == render ) {
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
@@ -1972,14 +1975,14 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
// we start with a vertex in the middle...
|
// we start with a vertex in the middle...
|
||||||
vertices.emplace_back(
|
vertices.emplace_back(
|
||||||
glm::vec3{
|
glm::vec3{
|
||||||
oxz.x - origin.x,
|
oxz.x - m_origin.x,
|
||||||
oxz.y - origin.y,
|
oxz.y - m_origin.y,
|
||||||
oxz.z - origin.z },
|
oxz.z - m_origin.z },
|
||||||
glm::vec3{ 0.0f, 1.0f, 0.0f },
|
glm::vec3{ 0.0f, 1.0f, 0.0f },
|
||||||
glm::vec2{ 0.5f, 0.5f } );
|
glm::vec2{ 0.5f, 0.5f } );
|
||||||
// ...and add one extra vertex to close the fan...
|
// ...and add one extra vertex to close the fan...
|
||||||
u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x + origin.x ) / fTexLength;
|
u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x + m_origin.x ) / fTexLength;
|
||||||
v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z + origin.z ) / ( fTexRatio1 * fTexLength );
|
v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z + m_origin.z ) / ( fTexRatio1 * fTexLength );
|
||||||
vertices.emplace_back(
|
vertices.emplace_back(
|
||||||
glm::vec3 {
|
glm::vec3 {
|
||||||
SwitchExtension->vPoints[ 0 ].x,
|
SwitchExtension->vPoints[ 0 ].x,
|
||||||
@@ -1993,8 +1996,8 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
// ...then draw the precalculated rest
|
// ...then draw the precalculated rest
|
||||||
for (int i = pointcount + SwitchExtension->iRoads - 1; i >= 0; --i) {
|
for (int i = pointcount + SwitchExtension->iRoads - 1; i >= 0; --i) {
|
||||||
// mapowanie we współrzędnych scenerii
|
// mapowanie we współrzędnych scenerii
|
||||||
u = ( SwitchExtension->vPoints[ i ].x - oxz.x + origin.x ) / fTexLength;
|
u = ( SwitchExtension->vPoints[ i ].x - oxz.x + m_origin.x ) / fTexLength;
|
||||||
v = ( SwitchExtension->vPoints[ i ].z - oxz.z + origin.z ) / ( fTexRatio1 * fTexLength );
|
v = ( SwitchExtension->vPoints[ i ].z - oxz.z + m_origin.z ) / ( fTexRatio1 * fTexLength );
|
||||||
vertices.emplace_back(
|
vertices.emplace_back(
|
||||||
glm::vec3 {
|
glm::vec3 {
|
||||||
SwitchExtension->vPoints[ i ].x,
|
SwitchExtension->vPoints[ i ].x,
|
||||||
@@ -2068,7 +2071,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
if (m_material1) // jeśli podana była tekstura, generujemy trójkąty
|
if (m_material1) // jeśli podana była tekstura, generujemy trójkąty
|
||||||
{ // tworzenie trójkątów nawierzchni szosy
|
{ // tworzenie trójkątów nawierzchni szosy
|
||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
||||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
}
|
}
|
||||||
if (m_material2)
|
if (m_material2)
|
||||||
@@ -2128,19 +2131,19 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
|||||||
{-rozp2, -fTexHeight2, 0.f},
|
{-rozp2, -fTexHeight2, 0.f},
|
||||||
normalup,
|
normalup,
|
||||||
{0.0f, 0.f} }; // prawy brzeg prawego pobocza
|
{0.0f, 0.f} }; // prawy brzeg prawego pobocza
|
||||||
Segment->RenderLoft(vertices, origin, rpts1, -3, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, rpts1, -3, fTexLength);
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
Segment->RenderLoft(vertices, origin, rpts2, -3, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, rpts2, -3, fTexLength);
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // pobocza zwykłe, brak przechyłki
|
{ // pobocza zwykłe, brak przechyłki
|
||||||
Segment->RenderLoft(vertices, origin, rpts1, 3, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, rpts1, 3, fTexLength);
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
Segment->RenderLoft(vertices, origin, rpts2, 3, fTexLength);
|
Segment->RenderLoft(vertices, m_origin, rpts2, 3, fTexLength);
|
||||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -2463,20 +2466,19 @@ TTrack * TTrack::RaAnimate()
|
|||||||
{szyna[ i ].texture.x, 0.f} };
|
{szyna[ i ].texture.x, 0.f} };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const origin { pMyNode->m_rootposition };
|
|
||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
|
|
||||||
if (SwitchExtension->RightSwitch)
|
if (SwitchExtension->RightSwitch)
|
||||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||||
if( m_material1 ) {
|
if( m_material1 ) {
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
||||||
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( m_material2 ) {
|
if( m_material2 ) {
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
||||||
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -2484,13 +2486,13 @@ TTrack * TTrack::RaAnimate()
|
|||||||
else { // lewa działa lepiej niż prawa
|
else { // lewa działa lepiej niż prawa
|
||||||
if( m_material1 ) {
|
if( m_material1 ) {
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
||||||
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
if( m_material2 ) {
|
if( m_material2 ) {
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
||||||
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
||||||
vertices.clear();
|
vertices.clear();
|
||||||
}
|
}
|
||||||
@@ -2528,7 +2530,11 @@ TTrack * TTrack::RaAnimate()
|
|||||||
dynamic->Move( 0.000001 );
|
dynamic->Move( 0.000001 );
|
||||||
}
|
}
|
||||||
// NOTE: passing empty handle is a bit of a hack here. could be refactored into something more elegant
|
// NOTE: passing empty handle is a bit of a hack here. could be refactored into something more elegant
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
create_geometry( geometrybank_handle(), glm::dvec3() );
|
||||||
|
#else
|
||||||
create_geometry( geometrybank_handle() );
|
create_geometry( geometrybank_handle() );
|
||||||
|
#endif
|
||||||
} // animacja trwa nadal
|
} // animacja trwa nadal
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2650,14 +2656,6 @@ void TTrack::MovedUp1(float const dh)
|
|||||||
fTexHeight1 += dh;
|
fTexHeight1 += dh;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string TTrack::NameGet()
|
|
||||||
{ // ustalenie nazwy toru
|
|
||||||
if (this)
|
|
||||||
if (pMyNode)
|
|
||||||
return pMyNode->asName;
|
|
||||||
return "none";
|
|
||||||
};
|
|
||||||
|
|
||||||
void TTrack::VelocitySet(float v)
|
void TTrack::VelocitySet(float v)
|
||||||
{ // ustawienie prędkości z ograniczeniem do pierwotnej wartości (zapisanej w scenerii)
|
{ // ustawienie prędkości z ograniczeniem do pierwotnej wartości (zapisanej w scenerii)
|
||||||
if (SwitchExtension ? SwitchExtension->fVelocity >= 0.0 : false)
|
if (SwitchExtension ? SwitchExtension->fVelocity >= 0.0 : false)
|
||||||
@@ -2677,17 +2675,17 @@ double TTrack::VelocityGet()
|
|||||||
void TTrack::ConnectionsLog()
|
void TTrack::ConnectionsLog()
|
||||||
{ // wypisanie informacji o połączeniach
|
{ // wypisanie informacji o połączeniach
|
||||||
int i;
|
int i;
|
||||||
WriteLog("--> tt_Cross named " + pMyNode->asName);
|
WriteLog("--> tt_Cross named " + m_name);
|
||||||
if (eType == tt_Cross)
|
if (eType == tt_Cross)
|
||||||
for (i = 0; i < 2; ++i)
|
for (i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
if (SwitchExtension->pPrevs[i])
|
if (SwitchExtension->pPrevs[i])
|
||||||
WriteLog("Point " + std::to_string(i + i + 1) + " -> track " +
|
WriteLog("Point " + std::to_string(i + i + 1) + " -> track " +
|
||||||
SwitchExtension->pPrevs[i]->pMyNode->asName + ":" +
|
SwitchExtension->pPrevs[i]->m_name + ":" +
|
||||||
std::to_string(int(SwitchExtension->iPrevDirection[i])));
|
std::to_string(int(SwitchExtension->iPrevDirection[i])));
|
||||||
if (SwitchExtension->pNexts[i])
|
if (SwitchExtension->pNexts[i])
|
||||||
WriteLog("Point " + std::to_string(i + i + 2) + " -> track " +
|
WriteLog("Point " + std::to_string(i + i + 2) + " -> track " +
|
||||||
SwitchExtension->pNexts[i]->pMyNode->asName + ":" +
|
SwitchExtension->pNexts[i]->m_name + ":" +
|
||||||
std::to_string(int(SwitchExtension->iNextDirection[i])));
|
std::to_string(int(SwitchExtension->iNextDirection[i])));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2741,3 +2739,182 @@ TTrack * TTrack::Connected(int s, double &d) const
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// legacy method, initializes tracks after deserialization from scenario file
|
||||||
|
void
|
||||||
|
path_table::InitTracks() {
|
||||||
|
/*
|
||||||
|
TGroundNode *Model;
|
||||||
|
int iConnection;
|
||||||
|
|
||||||
|
for( auto *track : m_paths ) {
|
||||||
|
|
||||||
|
track->AssignEvents(
|
||||||
|
simulation::Events.FindEvent( track->asEvent0Name ),
|
||||||
|
simulation::Events.FindEvent( track->asEvent1Name ),
|
||||||
|
simulation::Events.FindEvent( track->asEvent2Name ) );
|
||||||
|
track->AssignallEvents(
|
||||||
|
simulation::Events.FindEvent( track->asEventall0Name ),
|
||||||
|
simulation::Events.FindEvent( track->asEventall1Name ),
|
||||||
|
simulation::Events.FindEvent( track->asEventall2Name ) );
|
||||||
|
|
||||||
|
auto const trackname { track->name() };
|
||||||
|
|
||||||
|
if( ( Global::iHiddenEvents & 1 )
|
||||||
|
&& ( false == trackname.empty() ) ) {
|
||||||
|
// jeśli podana jest nazwa torów, można szukać eventów skojarzonych przez nazwę
|
||||||
|
track->AssignEvents(
|
||||||
|
simulation::Events.FindEvent( trackname + ":event0" ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":event1" ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":event2" ) );
|
||||||
|
track->AssignallEvents(
|
||||||
|
simulation::Events.FindEvent( trackname + ":eventall0" ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":eventall1" ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":eventall2" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (track->eType) {
|
||||||
|
case tt_Table: {
|
||||||
|
// obrotnicę też łączymy na starcie z innymi torami
|
||||||
|
// szukamy modelu o tej samej nazwie
|
||||||
|
Model = FindGroundNode(Current->asName, TP_MODEL);
|
||||||
|
// wiązanie toru z modelem obrotnicy
|
||||||
|
track->RaAssign(
|
||||||
|
Current,
|
||||||
|
( Model ?
|
||||||
|
Model->Model :
|
||||||
|
nullptr ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":done" ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":joined" ) );
|
||||||
|
if( Model == nullptr ) {
|
||||||
|
// jak nie ma modelu to pewnie jest wykolejnica, a ta jest domyślnie zamknięta i wykoleja
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// jak coś pójdzie źle, to robimy z tego normalny tor
|
||||||
|
}
|
||||||
|
case tt_Normal: {
|
||||||
|
// tylko proste są podłączane do rozjazdów, stąd dwa rozjazdy się nie połączą ze sobą
|
||||||
|
if( track->CurrentPrev() == nullptr ) {
|
||||||
|
// tylko jeśli jeszcze nie podłączony
|
||||||
|
auto *matchingtrack = simulation::Region.FindTrack( track->CurrentSegment()->FastGetPoint_0(), iConnection, track );
|
||||||
|
switch( iConnection ) {
|
||||||
|
case -1: // Ra: pierwsza koncepcja zawijania samochodów i statków
|
||||||
|
// if ((Track->iCategoryFlag&1)==0) //jeśli nie jest torem szynowym
|
||||||
|
// Track->ConnectPrevPrev(Track,0); //łączenie końca odcinka do samego siebie
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
track->ConnectPrevPrev( matchingtrack, 0 );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
track->ConnectPrevNext( matchingtrack, 1 );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
track->ConnectPrevPrev( matchingtrack, 0 ); // do Point1 pierwszego
|
||||||
|
matchingtrack->SetConnections( 0 ); // zapamiętanie ustawień w Segmencie
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
track->ConnectPrevNext( matchingtrack, 1 ); // do Point2 pierwszego
|
||||||
|
matchingtrack->SetConnections( 0 ); // zapamiętanie ustawień w Segmencie
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
matchingtrack->Switch( 1 );
|
||||||
|
track->ConnectPrevPrev( matchingtrack, 2 ); // do Point1 drugiego
|
||||||
|
matchingtrack->SetConnections( 1 ); // robi też Switch(0)
|
||||||
|
matchingtrack->Switch( 0 );
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
matchingtrack->Switch( 1 );
|
||||||
|
track->ConnectPrevNext( matchingtrack, 3 ); // do Point2 drugiego
|
||||||
|
matchingtrack->SetConnections( 1 ); // robi też Switch(0)
|
||||||
|
matchingtrack->Switch( 0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( track->CurrentNext() == nullptr ) {
|
||||||
|
// tylko jeśli jeszcze nie podłączony
|
||||||
|
auto *matchingtrack = simulation::Region.FindTrack( track->CurrentSegment()->FastGetPoint_1(), iConnection, track );
|
||||||
|
switch( iConnection ) {
|
||||||
|
case -1: // Ra: pierwsza koncepcja zawijania samochodów i statków
|
||||||
|
// if ((Track->iCategoryFlag&1)==0) //jeśli nie jest torem szynowym
|
||||||
|
// Track->ConnectNextNext(Track,1); //łączenie końca odcinka do samego siebie
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
track->ConnectNextPrev( matchingtrack, 0 );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
track->ConnectNextNext( matchingtrack, 1 );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
track->ConnectNextPrev( matchingtrack, 0 );
|
||||||
|
matchingtrack->SetConnections( 0 ); // zapamiętanie ustawień w Segmencie
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
track->ConnectNextNext( matchingtrack, 1 );
|
||||||
|
matchingtrack->SetConnections( 0 ); // zapamiętanie ustawień w Segmencie
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
matchingtrack->Switch( 1 );
|
||||||
|
track->ConnectNextPrev( matchingtrack, 2 );
|
||||||
|
matchingtrack->SetConnections( 1 ); // robi też Switch(0)
|
||||||
|
// tmp->Switch(0);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
matchingtrack->Switch( 1 );
|
||||||
|
track->ConnectNextNext( matchingtrack, 3 );
|
||||||
|
matchingtrack->SetConnections( 1 ); // robi też Switch(0)
|
||||||
|
// tmp->Switch(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case tt_Switch: {
|
||||||
|
// dla rozjazdów szukamy eventów sygnalizacji rozprucia
|
||||||
|
track->AssignForcedEvents(
|
||||||
|
simulation::Events.FindEvent( trackname + ":forced+" ),
|
||||||
|
simulation::Events.FindEvent( trackname + ":forced-" ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
// pobranie nazwy odcinka izolowanego
|
||||||
|
auto const isolatedname { track->IsolatedName() };
|
||||||
|
if( false == isolatedname.empty() ) {
|
||||||
|
// jeśli została zwrócona nazwa
|
||||||
|
track->IsolatedEventsAssign(
|
||||||
|
simulation::Events.FindEvent( isolatedname + ":busy" ),
|
||||||
|
simulation::Events.FindEvent( isolatedname + ":free" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( trackname[ 0 ] == '*' )
|
||||||
|
&& ( !track->CurrentPrev() && track->CurrentNext() ) ) {
|
||||||
|
// możliwy portal, jeśli nie podłączony od strony 1
|
||||||
|
// ustawienie flagi portalu
|
||||||
|
track->iCategoryFlag |= 0x100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TIsolated *isolated = TIsolated::Root();
|
||||||
|
while( isolated ) {
|
||||||
|
// jeśli się znajdzie, to podać wskaźnik
|
||||||
|
auto *memorycell = simulation::Memory.find( isolated->asName ); // czy jest komóka o odpowiedniej nazwie
|
||||||
|
if( memorycell != nullptr ) {
|
||||||
|
// przypisanie powiązanej komórki
|
||||||
|
isolated->pMemCell = memorycell;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// utworzenie automatycznej komórki
|
||||||
|
// TODO: determine suitable location for this one, create and add world reference node
|
||||||
|
auto *memorycell = new TMemCell( isolated->asName ); // to nie musi mieć nazwy, nazwa w wyszukiwarce wystarczy
|
||||||
|
simulation::Memory.insert( memorycell );
|
||||||
|
isolated->pMemCell = memorycell; // wskaźnik komóki przekazany do odcinka izolowanego
|
||||||
|
}
|
||||||
|
isolated = isolated->Next();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|||||||
45
Track.h
45
Track.h
@@ -13,8 +13,10 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
#include "scenenode.h"
|
||||||
#include "Segment.h"
|
#include "Segment.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
#include "names.h"
|
||||||
|
|
||||||
enum TTrackType {
|
enum TTrackType {
|
||||||
tt_Unknown,
|
tt_Unknown,
|
||||||
@@ -112,12 +114,12 @@ class TIsolated
|
|||||||
};
|
};
|
||||||
|
|
||||||
// trajektoria ruchu - opakowanie
|
// trajektoria ruchu - opakowanie
|
||||||
class TTrack {
|
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
|
// 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;
|
||||||
@@ -126,7 +128,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...)
|
||||||
@@ -134,6 +136,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;
|
||||||
@@ -167,7 +170,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:
|
||||||
@@ -177,11 +179,13 @@ 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 TTrack * Create400m(int what, double dx);
|
static TTrack * Create400m(int what, double dx);
|
||||||
TTrack * NullCreate(int dir);
|
TTrack * NullCreate(int dir);
|
||||||
@@ -218,7 +222,7 @@ public:
|
|||||||
SwitchExtension != nullptr ?
|
SwitchExtension != nullptr ?
|
||||||
SwitchExtension->iRoads - 1 :
|
SwitchExtension->iRoads - 1 :
|
||||||
1 ); }
|
1 ); }
|
||||||
void Load(cParser *parser, Math3D::vector3 pOrigin, std::string name);
|
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);
|
||||||
@@ -226,7 +230,16 @@ public:
|
|||||||
bool AddDynamicObject(TDynamicObject *Dynamic);
|
bool AddDynamicObject(TDynamicObject *Dynamic);
|
||||||
bool RemoveDynamicObject(TDynamicObject *Dynamic);
|
bool RemoveDynamicObject(TDynamicObject *Dynamic);
|
||||||
|
|
||||||
void create_geometry(geometrybank_handle const &Bank); // wypełnianie VBO
|
// set origin point
|
||||||
|
void
|
||||||
|
origin( glm::dvec3 Origin ) {
|
||||||
|
m_origin = Origin; }
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
void create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ); // wypełnianie VBO
|
||||||
|
#else
|
||||||
|
void create_geometry( geometrybank_handle const &Bank ); // wypełnianie VBO
|
||||||
|
#endif
|
||||||
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
|
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
|
||||||
|
|
||||||
void RaOwnerSet(TSubRect *o) {
|
void RaOwnerSet(TSubRect *o) {
|
||||||
@@ -247,7 +260,6 @@ public:
|
|||||||
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);
|
||||||
double VelocityGet();
|
double VelocityGet();
|
||||||
void ConnectionsLog();
|
void ConnectionsLog();
|
||||||
@@ -257,4 +269,15 @@ public:
|
|||||||
void EnvironmentReset();
|
void EnvironmentReset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// collection of virtual tracks and roads present in the scene
|
||||||
|
class path_table : public basic_table<TTrack> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// legacy method, initializes tracks after deserialization from scenario file
|
||||||
|
void
|
||||||
|
InitTracks();
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
389
Traction.cpp
389
Traction.cpp
@@ -90,8 +90,91 @@ jawnie nazwę sekcji, ewentualnie nazwę zasilacza (zostanie zastąpiona wskazan
|
|||||||
sekcji z sąsiedniego przęsła).
|
sekcji z sąsiedniego przęsła).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TTraction::TTraction( scene::node_data const &Nodedata ) : basic_node( Nodedata ) {}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
m_location = interpolate( pPoint2, pPoint1, 0.5 );
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t
|
std::size_t
|
||||||
TTraction::create_geometry( geometrybank_handle const &Bank, glm::dvec3 const &Origin ) {
|
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 +189,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 +213,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 +224,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 +235,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 +245,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 +262,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 +285,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 +306,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 +336,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 );
|
||||||
}
|
}
|
||||||
@@ -523,3 +606,211 @@ TTraction::wire_color() const {
|
|||||||
}
|
}
|
||||||
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 iConnection;
|
||||||
|
std::string name;
|
||||||
|
for( auto *traction : m_items ) {
|
||||||
|
// podłączenie do zasilacza, żeby można było sumować prąd kilku pojazdów
|
||||||
|
// a jednocześnie z jednego miejsca zmieniać napięcie eventem
|
||||||
|
// wykonywane najpierw, żeby można było logować podłączenie 2 zasilaczy do jednego drutu
|
||||||
|
// izolator zawieszony na przęśle jest ma być osobnym odcinkiem drutu o długości ok. 1m,
|
||||||
|
// podłączonym do zasilacza o nazwie "*" (gwiazka); "none" nie będzie odpowiednie
|
||||||
|
nTemp = FindGroundNode(traction->asPowerSupplyName, TP_TRACTIONPOWERSOURCE);
|
||||||
|
if (nTemp) // jak zasilacz znaleziony
|
||||||
|
traction->PowerSet(nTemp->psTractionPowerSource); // to podłączyć do przęsła
|
||||||
|
else if (traction->asPowerSupplyName != "*") // gwiazdka dla przęsła z izolatorem
|
||||||
|
if (traction->asPowerSupplyName != "none") // dopuszczamy na razie brak podłączenia?
|
||||||
|
{ // logowanie błędu i utworzenie zasilacza o domyślnej zawartości
|
||||||
|
ErrorLog("Missed TractionPowerSource: " + traction->asPowerSupplyName);
|
||||||
|
nTemp = new TGroundNode();
|
||||||
|
nTemp->iType = TP_TRACTIONPOWERSOURCE;
|
||||||
|
nTemp->asName = traction->asPowerSupplyName;
|
||||||
|
nTemp->psTractionPowerSource = new TTractionPowerSource(nTemp);
|
||||||
|
nTemp->psTractionPowerSource->Init(traction->NominalVoltage, traction->MaxCurrent);
|
||||||
|
nTemp->nNext = nRootOfType[nTemp->iType]; // ostatni dodany dołączamy na końcu
|
||||||
|
// nowego
|
||||||
|
nRootOfType[nTemp->iType] = nTemp; // ustawienie nowego na początku listy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto *traction : m_items ) {
|
||||||
|
|
||||||
|
if (!traction->hvNext[0]) // tylko jeśli jeszcze nie podłączony
|
||||||
|
{
|
||||||
|
tmp = FindTraction(traction->pPoint1, iConnection, nCurrent);
|
||||||
|
switch (iConnection)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
traction->Connect(0, tmp, 0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
traction->Connect(0, tmp, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (traction->hvNext[0]) // jeśli został podłączony
|
||||||
|
if (traction->psSection && tmp->psSection) // tylko przęsło z izolatorem może nie
|
||||||
|
// mieć zasilania, bo ma 2, trzeba
|
||||||
|
// sprawdzać sąsiednie
|
||||||
|
if (traction->psSection !=
|
||||||
|
tmp->psSection) // połączone odcinki mają różne zasilacze
|
||||||
|
{ // to może być albo podłączenie podstacji lub kabiny sekcyjnej do sekcji, albo
|
||||||
|
// błąd
|
||||||
|
if (traction->psSection->bSection && !tmp->psSection->bSection)
|
||||||
|
{ //(tmp->psSection) jest podstacją, a (Traction->psSection) nazwą sekcji
|
||||||
|
tmp->PowerSet(traction->psSection); // zastąpienie wskazaniem sekcji
|
||||||
|
}
|
||||||
|
else if (!traction->psSection->bSection && tmp->psSection->bSection)
|
||||||
|
{ //(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
|
||||||
|
traction->PowerSet(tmp->psSection); // zastąpienie wskazaniem sekcji
|
||||||
|
}
|
||||||
|
else // jeśli obie to sekcje albo obie podstacje, to będzie błąd
|
||||||
|
ErrorLog("Bad power: at " +
|
||||||
|
to_string(traction->pPoint1.x, 2, 6) + " " +
|
||||||
|
to_string(traction->pPoint1.y, 2, 6) + " " +
|
||||||
|
to_string(traction->pPoint1.z, 2, 6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!traction->hvNext[1]) // tylko jeśli jeszcze nie podłączony
|
||||||
|
{
|
||||||
|
tmp = FindTraction(traction->pPoint2, iConnection, nCurrent);
|
||||||
|
switch (iConnection)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
traction->Connect(1, tmp, 0);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
traction->Connect(1, tmp, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (traction->hvNext[1]) // jeśli został podłączony
|
||||||
|
if (traction->psSection && tmp->psSection) // tylko przęsło z izolatorem może nie
|
||||||
|
// mieć zasilania, bo ma 2, trzeba
|
||||||
|
// sprawdzać sąsiednie
|
||||||
|
if (traction->psSection != tmp->psSection)
|
||||||
|
{ // to może być albo podłączenie podstacji lub kabiny sekcyjnej do sekcji, albo
|
||||||
|
// błąd
|
||||||
|
if (traction->psSection->bSection && !tmp->psSection->bSection)
|
||||||
|
{ //(tmp->psSection) jest podstacją, a (Traction->psSection) nazwą sekcji
|
||||||
|
tmp->PowerSet(traction->psSection); // zastąpienie wskazaniem sekcji
|
||||||
|
}
|
||||||
|
else if (!traction->psSection->bSection && tmp->psSection->bSection)
|
||||||
|
{ //(Traction->psSection) jest podstacją, a (tmp->psSection) nazwą sekcji
|
||||||
|
traction->PowerSet(tmp->psSection); // zastąpienie wskazaniem sekcji
|
||||||
|
}
|
||||||
|
else // jeśli obie to sekcje albo obie podstacje, to będzie błąd
|
||||||
|
ErrorLog("Bad power: at " +
|
||||||
|
to_string(traction->pPoint2.x, 2, 6) + " " +
|
||||||
|
to_string(traction->pPoint2.y, 2, 6) + " " +
|
||||||
|
to_string(traction->pPoint2.z, 2, 6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iConnection = 0; // teraz będzie licznikiem końców
|
||||||
|
for( auto *traction : m_items ) {
|
||||||
|
// operacje mające na celu wykrywanie bieżni wspólnych i łączenie przęseł naprążania
|
||||||
|
if (traction->WhereIs()) // oznakowanie przedostatnich przęseł
|
||||||
|
{ // poszukiwanie bieżni wspólnej dla przedostatnich przęseł, również w celu połączenia
|
||||||
|
// zasilania
|
||||||
|
// to się nie sprawdza, bo połączyć się mogą dwa niezasilane odcinki jako najbliższe
|
||||||
|
// sobie
|
||||||
|
// nCurrent->hvTraction->hvParallel=TractionNearestFind(nCurrent->pCenter,0,nCurrent);
|
||||||
|
// //szukanie najbliższego przęsła
|
||||||
|
// trzeba by zliczać końce, a potem wpisać je do tablicy, aby sukcesywnie podłączać do
|
||||||
|
// zasilaczy
|
||||||
|
traction->iTries = 5; // oznaczanie końcowych
|
||||||
|
++iConnection;
|
||||||
|
}
|
||||||
|
if (traction->fResistance[0] == 0.0)
|
||||||
|
{
|
||||||
|
traction->ResistanceCalc(); // obliczanie przęseł w segmencie z bezpośrednim zasilaniem
|
||||||
|
// ErrorLog("Section "+nCurrent->hvTraction->asPowerSupplyName+" connected"); //jako
|
||||||
|
// niby błąd będzie bardziej widoczne
|
||||||
|
traction->iTries = 0; // nie potrzeba mu szukać zasilania
|
||||||
|
}
|
||||||
|
// if (!Traction->hvParallel) //jeszcze utworzyć pętle z bieżni wspólnych
|
||||||
|
}
|
||||||
|
int zg = 0; // zgodność kierunku przęseł, tymczasowo iterator do tabeli końców
|
||||||
|
// końców jest ok. 10 razy mniej niż wszystkich przęseł (Quark: 216)
|
||||||
|
TGroundNode **nEnds = new TGroundNode *[iConnection];
|
||||||
|
for( auto *traction : m_items ) {
|
||||||
|
//łączenie bieżni wspólnych, w tym oznaczanie niepodanych jawnie
|
||||||
|
if (!traction->asParallel.empty()) // będzie wskaźnik na inne przęsło
|
||||||
|
if( ( traction->asParallel == "none" )
|
||||||
|
|| ( traction->asParallel == "*" ) ) {
|
||||||
|
// jeśli nieokreślone
|
||||||
|
traction->iLast = 2; // jakby przedostatni - niech po prostu szuka (iLast już przeliczone)
|
||||||
|
}
|
||||||
|
else if (!traction->hvParallel) // jeśli jeszcze nie został włączony w kółko
|
||||||
|
{
|
||||||
|
auto *nTemp = find( traction->asParallel );
|
||||||
|
if (nTemp)
|
||||||
|
{ // o ile zostanie znalezione przęsło o takiej nazwie
|
||||||
|
if (!nTemp->hvParallel) // jeśli tamten jeszcze nie ma wskaźnika bieżni wspólnej
|
||||||
|
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)
|
||||||
|
ErrorLog("Missed overhead: " + traction->asParallel); // logowanie braku
|
||||||
|
}
|
||||||
|
if (traction->iTries > 0) // jeśli zaznaczony do podłączenia
|
||||||
|
// if (!nCurrent->hvTraction->psPower[0]||!nCurrent->hvTraction->psPower[1])
|
||||||
|
if (zg < iConnection) // zabezpieczenie
|
||||||
|
nEnds[zg++] = nCurrent; // wypełnianie tabeli końców w celu szukania im połączeń
|
||||||
|
}
|
||||||
|
while( zg < iConnection ) {
|
||||||
|
// zapełnienie do końca tablicy, jeśli by jakieś końce wypadły
|
||||||
|
nEnds[ zg++ ] = nullptr;
|
||||||
|
}
|
||||||
|
zg = 1; // nieefektywny przebieg kończy łączenie
|
||||||
|
while (zg)
|
||||||
|
{ // ustalenie zastępczej rezystancji dla każdego przęsła
|
||||||
|
zg = 0; // flaga podłączonych przęseł końcowych: -1=puste wskaźniki, 0=coś zostało,
|
||||||
|
// 1=wykonano łączenie
|
||||||
|
for (int i = 0; i < iConnection; ++i)
|
||||||
|
if (nEnds[i]) // załatwione będziemy zerować
|
||||||
|
{ // każdy przebieg to próba podłączenia końca segmentu naprężania do innego zasilanego
|
||||||
|
// przęsła
|
||||||
|
if (nEnds[i]->hvTraction->hvNext[0])
|
||||||
|
{ // jeśli końcowy ma ciąg dalszy od strony 0 (Point1), szukamy odcinka najbliższego
|
||||||
|
// do Point2
|
||||||
|
if (TractionNearestFind(nEnds[i]->hvTraction->pPoint2, 0,
|
||||||
|
nEnds[i])) // poszukiwanie przęsła
|
||||||
|
{
|
||||||
|
nEnds[i] = NULL;
|
||||||
|
zg = 1; // jak coś zostało podłączone, to może zasilanie gdzieś dodatkowo
|
||||||
|
// dotrze
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nEnds[i]->hvTraction->hvNext[1])
|
||||||
|
{ // jeśli końcowy ma ciąg dalszy od strony 1 (Point2), szukamy odcinka najbliższego
|
||||||
|
// do Point1
|
||||||
|
if (TractionNearestFind(nEnds[i]->hvTraction->pPoint1, 1,
|
||||||
|
nEnds[i])) // poszukiwanie przęsła
|
||||||
|
{
|
||||||
|
nEnds[i] = NULL;
|
||||||
|
zg = 1; // jak coś zostało podłączone, to może zasilanie gdzieś dodatkowo
|
||||||
|
// dotrze
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // gdy koniec jest samotny, to na razie nie zostanie podłączony (nie powinno
|
||||||
|
// takich być)
|
||||||
|
nEnds[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] nEnds; // nie potrzebne już
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|||||||
38
Traction.h
38
Traction.h
@@ -10,14 +10,16 @@ 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"
|
||||||
|
|
||||||
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
|
||||||
@@ -29,7 +31,7 @@ class TTraction
|
|||||||
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 };
|
||||||
@@ -47,11 +49,22 @@ class TTraction
|
|||||||
int iTries { 0 };
|
int iTries { 0 };
|
||||||
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 );
|
||||||
|
virtual ~TTraction() = default;
|
||||||
|
|
||||||
|
void Load( cParser *parser, glm::dvec3 const &pOrigin );
|
||||||
|
// set origin point
|
||||||
|
void
|
||||||
|
origin( glm::dvec3 Origin ) {
|
||||||
|
m_origin = Origin; }
|
||||||
// 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();
|
||||||
@@ -63,4 +76,15 @@ 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();
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1568,7 +1568,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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
Train.h
2
Train.h
@@ -73,6 +73,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)
|
||||||
|
|||||||
65
World.cpp
65
World.cpp
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
#include "simulation.h"
|
||||||
#include "Logs.h"
|
#include "Logs.h"
|
||||||
#include "MdlMngr.h"
|
#include "MdlMngr.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
@@ -242,6 +243,7 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
|||||||
GfxRenderer.Render();
|
GfxRenderer.Render();
|
||||||
|
|
||||||
WriteLog( "World setup..." );
|
WriteLog( "World setup..." );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
if( true == Ground.Init( Global::SceneryFile ) ) {
|
if( true == Ground.Init( Global::SceneryFile ) ) {
|
||||||
WriteLog( "...world setup done" );
|
WriteLog( "...world setup done" );
|
||||||
}
|
}
|
||||||
@@ -249,6 +251,9 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
|||||||
ErrorLog( "...world setup failed" );
|
ErrorLog( "...world setup failed" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if( false == simulation::State.deserialize( Global::SceneryFile ) ) { return false; }
|
||||||
|
#endif
|
||||||
|
|
||||||
simulation::Time.init();
|
simulation::Time.init();
|
||||||
|
|
||||||
@@ -299,6 +304,7 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
|||||||
|
|
||||||
// if (!Global::bMultiplayer) //na razie włączone
|
// if (!Global::bMultiplayer) //na razie włączone
|
||||||
{ // eventy aktywowane z klawiatury tylko dla jednego użytkownika
|
{ // eventy aktywowane z klawiatury tylko dla jednego użytkownika
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
KeyEvents[0] = Ground.FindEvent("keyctrl00");
|
KeyEvents[0] = Ground.FindEvent("keyctrl00");
|
||||||
KeyEvents[1] = Ground.FindEvent("keyctrl01");
|
KeyEvents[1] = Ground.FindEvent("keyctrl01");
|
||||||
KeyEvents[2] = Ground.FindEvent("keyctrl02");
|
KeyEvents[2] = Ground.FindEvent("keyctrl02");
|
||||||
@@ -309,6 +315,18 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
|||||||
KeyEvents[7] = Ground.FindEvent("keyctrl07");
|
KeyEvents[7] = Ground.FindEvent("keyctrl07");
|
||||||
KeyEvents[8] = Ground.FindEvent("keyctrl08");
|
KeyEvents[8] = Ground.FindEvent("keyctrl08");
|
||||||
KeyEvents[9] = Ground.FindEvent("keyctrl09");
|
KeyEvents[9] = Ground.FindEvent("keyctrl09");
|
||||||
|
#else
|
||||||
|
KeyEvents[ 0 ] = simulation::Events.FindEvent( "keyctrl00" );
|
||||||
|
KeyEvents[ 1 ] = simulation::Events.FindEvent( "keyctrl01" );
|
||||||
|
KeyEvents[ 2 ] = simulation::Events.FindEvent( "keyctrl02" );
|
||||||
|
KeyEvents[ 3 ] = simulation::Events.FindEvent( "keyctrl03" );
|
||||||
|
KeyEvents[ 4 ] = simulation::Events.FindEvent( "keyctrl04" );
|
||||||
|
KeyEvents[ 5 ] = simulation::Events.FindEvent( "keyctrl05" );
|
||||||
|
KeyEvents[ 6 ] = simulation::Events.FindEvent( "keyctrl06" );
|
||||||
|
KeyEvents[ 7 ] = simulation::Events.FindEvent( "keyctrl07" );
|
||||||
|
KeyEvents[ 8 ] = simulation::Events.FindEvent( "keyctrl08" );
|
||||||
|
KeyEvents[ 9 ] = simulation::Events.FindEvent( "keyctrl09" );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteLog( "Load time: " +
|
WriteLog( "Load time: " +
|
||||||
@@ -396,7 +414,11 @@ void TWorld::OnKeyDown(int cKey)
|
|||||||
{ // z [Shift] uruchomienie eventu
|
{ // z [Shift] uruchomienie eventu
|
||||||
if (!Global::iPause) // podczas pauzy klawisze nie działają
|
if (!Global::iPause) // podczas pauzy klawisze nie działają
|
||||||
if (KeyEvents[i])
|
if (KeyEvents[i])
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Ground.AddToQuery(KeyEvents[i], NULL);
|
Ground.AddToQuery(KeyEvents[i], NULL);
|
||||||
|
#else
|
||||||
|
simulation::Events.AddToQuery( KeyEvents[ i ], NULL );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else // zapamiętywanie kamery może działać podczas pauzy
|
else // zapamiętywanie kamery może działać podczas pauzy
|
||||||
if (FreeFlyModeFlag) // w trybie latania można przeskakiwać do ustawionych kamer
|
if (FreeFlyModeFlag) // w trybie latania można przeskakiwać do ustawionych kamer
|
||||||
@@ -685,8 +707,7 @@ void TWorld::OnKeyDown(int cKey)
|
|||||||
temp->MoverParameters->DecBrakeMult())
|
temp->MoverParameters->DecBrakeMult())
|
||||||
if (Train)
|
if (Train)
|
||||||
{ // dźwięk oczywiście jest w kabinie
|
{ // dźwięk oczywiście jest w kabinie
|
||||||
Train->dsbSwitch->SetVolume(DSBVOLUME_MAX);
|
Train->play_sound( Train->dsbSwitch );
|
||||||
Train->dsbSwitch->Play(0, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -715,8 +736,7 @@ void TWorld::OnKeyDown(int cKey)
|
|||||||
tmp->iLights[CouplNr] = (tmp->iLights[CouplNr] & ~mask) | set;
|
tmp->iLights[CouplNr] = (tmp->iLights[CouplNr] & ~mask) | set;
|
||||||
if (Train)
|
if (Train)
|
||||||
{ // Ra: ten dźwięk z kabiny to przegięcie, ale na razie zostawiam
|
{ // Ra: ten dźwięk z kabiny to przegięcie, ale na razie zostawiam
|
||||||
Train->dsbSwitch->SetVolume(DSBVOLUME_MAX);
|
Train->play_sound( Train->dsbSwitch );
|
||||||
Train->dsbSwitch->Play(0, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -736,8 +756,7 @@ void TWorld::OnKeyDown(int cKey)
|
|||||||
if (temp->MoverParameters->IncLocalBrakeLevelFAST())
|
if (temp->MoverParameters->IncLocalBrakeLevelFAST())
|
||||||
if (Train)
|
if (Train)
|
||||||
{ // dźwięk oczywiście jest w kabinie
|
{ // dźwięk oczywiście jest w kabinie
|
||||||
Train->dsbPneumaticRelay->SetVolume(-80);
|
Train->play_sound( Train->dsbPneumaticRelay );
|
||||||
Train->dsbPneumaticRelay->Play(0, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -756,8 +775,7 @@ void TWorld::OnKeyDown(int cKey)
|
|||||||
if (temp->MoverParameters->DecLocalBrakeLevelFAST())
|
if (temp->MoverParameters->DecLocalBrakeLevelFAST())
|
||||||
if (Train)
|
if (Train)
|
||||||
{ // dźwięk oczywiście jest w kabinie
|
{ // dźwięk oczywiście jest w kabinie
|
||||||
Train->dsbPneumaticRelay->SetVolume(-80);
|
Train->play_sound( Train->dsbPneumaticRelay );
|
||||||
Train->dsbPneumaticRelay->Play(0, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1045,10 +1063,14 @@ bool TWorld::Update()
|
|||||||
TSubModel::iInstance = 0;
|
TSubModel::iInstance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Ground.CheckQuery();
|
Ground.CheckQuery();
|
||||||
|
#else
|
||||||
|
simulation::Events.CheckQuery();
|
||||||
|
#endif
|
||||||
|
|
||||||
Ground.Update_Hidden();
|
Ground.Update_Hidden();
|
||||||
Ground.Update_Lights();
|
simulation::Lights.update();
|
||||||
|
|
||||||
// render time routines follow:
|
// render time routines follow:
|
||||||
|
|
||||||
@@ -1818,19 +1840,24 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
|
|||||||
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " scenery" + " rcvd");
|
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " scenery" + " rcvd");
|
||||||
Ground.WyslijString(Global::SceneryFile, 1); // nazwa scenerii
|
Ground.WyslijString(Global::SceneryFile, 1); // nazwa scenerii
|
||||||
break;
|
break;
|
||||||
case 2: // event
|
case 2: {
|
||||||
CommLog( Now() + " " + std::to_string(pRozkaz->iComm) + " " +
|
// event
|
||||||
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])) + " rcvd");
|
CommLog( Now() + " " + std::to_string( pRozkaz->iComm ) + " " +
|
||||||
if (Global::iMultiplayer)
|
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) + " rcvd" );
|
||||||
{ // WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
|
/*
|
||||||
|
// TODO: re-enable when messaging module is in place
|
||||||
|
if( Global::iMultiplayer ) {
|
||||||
|
// WriteLog("Komunikat: "+AnsiString(pRozkaz->Name1));
|
||||||
TEvent *e = Ground.FindEvent(
|
TEvent *e = Ground.FindEvent(
|
||||||
std::string(pRozkaz->cString + 1, (unsigned)(pRozkaz->cString[0])));
|
std::string( pRozkaz->cString + 1, (unsigned)( pRozkaz->cString[ 0 ] ) ) );
|
||||||
if (e)
|
if( e )
|
||||||
if ((e->Type == tp_Multiple) || (e->Type == tp_Lights) ||
|
if( ( e->Type == tp_Multiple ) || ( e->Type == tp_Lights ) ||
|
||||||
(e->evJoined != 0)) // tylko jawne albo niejawne Multiple
|
( e->evJoined != 0 ) ) // tylko jawne albo niejawne Multiple
|
||||||
Ground.AddToQuery(e, NULL); // drugi parametr to dynamic wywołujący - tu brak
|
Ground.AddToQuery( e, NULL ); // drugi parametr to dynamic wywołujący - tu brak
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 3: // rozkaz dla AI
|
case 3: // rozkaz dla AI
|
||||||
if (Global::iMultiplayer)
|
if (Global::iMultiplayer)
|
||||||
{
|
{
|
||||||
|
|||||||
1
World.h
1
World.h
@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Ground.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"
|
||||||
|
|||||||
@@ -228,6 +228,18 @@
|
|||||||
<ClCompile Include="material.cpp">
|
<ClCompile Include="material.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="scene.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="scenenode.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="simulation.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vertex.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Globals.h">
|
<ClInclude Include="Globals.h">
|
||||||
@@ -446,6 +458,18 @@
|
|||||||
<ClInclude Include="material.h">
|
<ClInclude Include="material.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="vertex.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="scene.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="scenenode.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="simulation.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="maszyna.rc">
|
<ResourceCompile Include="maszyna.rc">
|
||||||
|
|||||||
644
renderer.cpp
644
renderer.cpp
@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "simulation.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "train.h"
|
#include "train.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
@@ -53,9 +54,9 @@ opengl_camera::update_frustum( glm::mat4 const &Projection, glm::mat4 const &Mod
|
|||||||
|
|
||||||
// returns true if specified object is within camera frustum, false otherwise
|
// returns true if specified object is within camera frustum, false otherwise
|
||||||
bool
|
bool
|
||||||
opengl_camera::visible( bounding_area const &Area ) const {
|
opengl_camera::visible( scene::bounding_area const &Area ) const {
|
||||||
|
|
||||||
return ( m_frustum.sphere_inside( Area.center, Area.radius ) > 0.0f );
|
return ( m_frustum.sphere_inside( Area.center, Area.radius ) > 0.f );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -325,10 +326,10 @@ opengl_renderer::Render() {
|
|||||||
++m_framestamp;
|
++m_framestamp;
|
||||||
Render_pass( rendermode::color );
|
Render_pass( rendermode::color );
|
||||||
|
|
||||||
m_drawcount = m_drawqueue.size();
|
m_drawcount = m_cellqueue.size();
|
||||||
// accumulate last 20 frames worth of render time (cap at 1000 fps to prevent calculations going awry)
|
// accumulate last 20 frames worth of render time (cap at 1000 fps to prevent calculations going awry)
|
||||||
m_drawtimecolorpass = std::max( 20.f, 0.95f * m_drawtimecolorpass + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - drawstartcolorpass ) ).count() / 1000.f );
|
m_drawtimecolorpass = std::max( 20.f, 0.95f * m_drawtimecolorpass + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - drawstartcolorpass ) ).count() / 1000.f );
|
||||||
m_debuginfo += "frame total: " + to_string( m_drawtimecolorpass / 20.f, 2 ) + " msec (" + std::to_string( m_drawqueue.size() ) + " sectors) ";
|
m_debuginfo += "frame total: " + to_string( m_drawtimecolorpass / 20.f, 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors) ";
|
||||||
|
|
||||||
glfwSwapBuffers( m_window );
|
glfwSwapBuffers( m_window );
|
||||||
|
|
||||||
@@ -360,12 +361,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
m_worldcamera,
|
m_worldcamera,
|
||||||
rendermode::color,
|
rendermode::color,
|
||||||
0.f,
|
0.f,
|
||||||
std::min(
|
1.0,
|
||||||
1.f,
|
|
||||||
Global::shadowtune.depth / ( Global::BaseDrawRange * Global::fDistanceFactor )
|
|
||||||
* std::max(
|
|
||||||
1.f,
|
|
||||||
Global::ZoomFactor * 0.5f ) ),
|
|
||||||
true );
|
true );
|
||||||
#endif
|
#endif
|
||||||
// setup shadowmap matrix
|
// setup shadowmap matrix
|
||||||
@@ -433,10 +429,18 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
switch_units( true, true, true );
|
switch_units( true, true, true );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Render( &World.Ground );
|
Render( &World.Ground );
|
||||||
|
#else
|
||||||
|
Render( simulation::Region );
|
||||||
|
#endif
|
||||||
// ...translucent parts
|
// ...translucent parts
|
||||||
setup_drawing( true );
|
setup_drawing( true );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Render_Alpha( &World.Ground );
|
Render_Alpha( &World.Ground );
|
||||||
|
#else
|
||||||
|
Render_Alpha( simulation::Region );
|
||||||
|
#endif
|
||||||
if( World.Train != nullptr ) {
|
if( World.Train != nullptr ) {
|
||||||
// cab render is performed without shadows, due to low resolution and number of models without windows :|
|
// cab render is performed without shadows, due to low resolution and number of models without windows :|
|
||||||
switch_units( true, false, false );
|
switch_units( true, false, false );
|
||||||
@@ -486,7 +490,11 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
#else
|
#else
|
||||||
setup_units( false, false, false );
|
setup_units( false, false, false );
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Render( &World.Ground );
|
Render( &World.Ground );
|
||||||
|
#else
|
||||||
|
Render( simulation::Region );
|
||||||
|
#endif
|
||||||
// post-render restore
|
// post-render restore
|
||||||
::glDisable( GL_POLYGON_OFFSET_FILL );
|
::glDisable( GL_POLYGON_OFFSET_FILL );
|
||||||
::glDisable( GL_SCISSOR_TEST );
|
::glDisable( GL_SCISSOR_TEST );
|
||||||
@@ -494,7 +502,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch back to primary render target
|
::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch back to primary render target
|
||||||
|
|
||||||
m_drawtimeshadowpass = 0.95f * m_drawtimeshadowpass + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - shadowdrawstart ) ).count() / 1000.f;
|
m_drawtimeshadowpass = 0.95f * m_drawtimeshadowpass + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - shadowdrawstart ) ).count() / 1000.f;
|
||||||
m_debuginfo += "shadows: " + to_string( m_drawtimeshadowpass / 20.f, 2 ) + " msec (" + std::to_string( m_drawqueue.size() ) + " sectors) ";
|
m_debuginfo += "shadows: " + to_string( m_drawtimeshadowpass / 20.f, 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors) ";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -516,7 +524,11 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
// opaque parts...
|
// opaque parts...
|
||||||
setup_drawing( false );
|
setup_drawing( false );
|
||||||
setup_units( true, true, true );
|
setup_units( true, true, true );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Render( &World.Ground );
|
Render( &World.Ground );
|
||||||
|
#else
|
||||||
|
Render( simulation::Region );
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
// reflections are limited to sky and ground only, the update rate is too low for anything else
|
// reflections are limited to sky and ground only, the update rate is too low for anything else
|
||||||
// ...translucent parts
|
// ...translucent parts
|
||||||
@@ -569,7 +581,11 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
// opaque parts...
|
// opaque parts...
|
||||||
setup_drawing( false );
|
setup_drawing( false );
|
||||||
setup_units( false, false, false );
|
setup_units( false, false, false );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
Render( &World.Ground );
|
Render( &World.Ground );
|
||||||
|
#else
|
||||||
|
Render( simulation::Region );
|
||||||
|
#endif
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1337,12 +1353,11 @@ opengl_renderer::Texture( texture_handle const Texture ) const {
|
|||||||
return m_textures.texture( Texture );
|
return m_textures.texture( Texture );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
|
||||||
bool
|
bool
|
||||||
opengl_renderer::Render( TGround *Ground ) {
|
opengl_renderer::Render( TGround *Ground ) {
|
||||||
|
|
||||||
m_drawqueue.clear();
|
m_cellqueue.clear();
|
||||||
|
|
||||||
glm::vec3 const cameraposition { m_renderpass.camera.position() };
|
glm::vec3 const cameraposition { m_renderpass.camera.position() };
|
||||||
int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 );
|
int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 );
|
||||||
@@ -1354,25 +1369,29 @@ opengl_renderer::Render( TGround *Ground ) {
|
|||||||
switch( m_renderpass.draw_mode ) {
|
switch( m_renderpass.draw_mode ) {
|
||||||
case rendermode::color: {
|
case rendermode::color: {
|
||||||
|
|
||||||
Update_Lights( Ground->m_lights );
|
Update_Lights( simulation::Lights );
|
||||||
|
|
||||||
for( int column = originx; column <= originx + segmentcount; ++column ) {
|
for( int column = originx; column <= originx + segmentcount; ++column ) {
|
||||||
for( int row = originz; row <= originz + segmentcount; ++row ) {
|
for( int row = originz; row <= originz + segmentcount; ++row ) {
|
||||||
|
|
||||||
auto *cell = &Ground->Rects[ column ][ row ];
|
auto *cell = &Ground->Rects[ column ][ row ];
|
||||||
|
#ifdef EU07_USE_DEBUG_CULLING
|
||||||
|
if( m_worldcamera.camera.visible( cell->m_area ) ) {
|
||||||
|
#else
|
||||||
if( m_renderpass.camera.visible( cell->m_area ) ) {
|
if( m_renderpass.camera.visible( cell->m_area ) ) {
|
||||||
|
#endif
|
||||||
Render( cell );
|
Render( cell );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// draw queue was filled while rendering content of ground cells. now sort the nodes based on their distance to viewer...
|
// draw queue was filled while rendering content of ground cells. now sort the nodes based on their distance to viewer...
|
||||||
std::sort(
|
std::sort(
|
||||||
std::begin( m_drawqueue ),
|
std::begin( m_cellqueue ),
|
||||||
std::end( m_drawqueue ),
|
std::end( m_cellqueue ),
|
||||||
[]( distancesubcell_pair const &Left, distancesubcell_pair const &Right ) {
|
[]( distancesubcell_pair const &Left, distancesubcell_pair const &Right ) {
|
||||||
return ( Left.first ) < ( Right.first ); } );
|
return ( Left.first ) < ( Right.first ); } );
|
||||||
// ...then render the opaque content of the visible subcells.
|
// ...then render the opaque content of the visible subcells.
|
||||||
for( auto subcellpair : m_drawqueue ) {
|
for( auto subcellpair : m_cellqueue ) {
|
||||||
Render( subcellpair.second );
|
Render( subcellpair.second );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1404,7 +1423,7 @@ opengl_renderer::Render( TGround *Ground ) {
|
|||||||
}
|
}
|
||||||
// they can also skip queue sorting, as they only deal with opaque geometry
|
// they can also skip queue sorting, as they only deal with opaque geometry
|
||||||
// NOTE: there's benefit from rendering front-to-back, but is it significant enough? TODO: investigate
|
// NOTE: there's benefit from rendering front-to-back, but is it significant enough? TODO: investigate
|
||||||
for( auto subcellpair : m_drawqueue ) {
|
for( auto subcellpair : m_cellqueue ) {
|
||||||
Render( subcellpair.second );
|
Render( subcellpair.second );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1475,7 +1494,7 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
|
|||||||
auto subcell = Groundcell->pSubRects + subcellindex;
|
auto subcell = Groundcell->pSubRects + subcellindex;
|
||||||
if( subcell->iNodeCount ) {
|
if( subcell->iNodeCount ) {
|
||||||
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
|
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
|
||||||
m_drawqueue.emplace_back(
|
m_cellqueue.emplace_back(
|
||||||
glm::length2( m_renderpass.camera.position() - glm::dvec3( subcell->m_area.center ) ),
|
glm::length2( m_renderpass.camera.position() - glm::dvec3( subcell->m_area.center ) ),
|
||||||
subcell );
|
subcell );
|
||||||
}
|
}
|
||||||
@@ -1577,6 +1596,407 @@ opengl_renderer::Render( TSubRect *Groundsubcell ) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
opengl_renderer::Render( scene::basic_region &Region ) {
|
||||||
|
|
||||||
|
m_sectionqueue.clear();
|
||||||
|
m_cellqueue.clear();
|
||||||
|
|
||||||
|
// build a list of region sections to render
|
||||||
|
glm::vec3 const cameraposition { m_renderpass.camera.position() };
|
||||||
|
auto const camerax = static_cast<int>( std::floor( cameraposition.x / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||||
|
auto const cameraz = static_cast<int>( std::floor( cameraposition.z / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||||
|
int const segmentcount = 2 * static_cast<int>( std::ceil( m_renderpass.draw_range * Global::fDistanceFactor / scene::EU07_SECTIONSIZE ) );
|
||||||
|
int const originx = camerax - segmentcount / 2;
|
||||||
|
int const originz = cameraz - segmentcount / 2;
|
||||||
|
|
||||||
|
for( int row = originz; row <= originz + segmentcount; ++row ) {
|
||||||
|
if( row < 0 ) { continue; }
|
||||||
|
if( row >= scene::EU07_REGIONSIDESECTIONCOUNT ) { break; }
|
||||||
|
for( int column = originx; column <= originx + segmentcount; ++column ) {
|
||||||
|
if( column < 0 ) { continue; }
|
||||||
|
if( column >= scene::EU07_REGIONSIDESECTIONCOUNT ) { break; }
|
||||||
|
auto §ion { Region.m_sections[ row * scene::EU07_REGIONSIDESECTIONCOUNT + column ] };
|
||||||
|
if( ( true == section.m_active )
|
||||||
|
#ifdef EU07_USE_DEBUG_CULLING
|
||||||
|
&& ( m_worldcamera.camera.visible( section.m_area ) ) ) {
|
||||||
|
#else
|
||||||
|
&& ( m_renderpass.camera.visible( section.m_area ) ) ) {
|
||||||
|
#endif
|
||||||
|
m_sectionqueue.emplace_back( §ion );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color: {
|
||||||
|
|
||||||
|
Update_Lights( simulation::Lights );
|
||||||
|
|
||||||
|
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
|
||||||
|
/*
|
||||||
|
// draw queue was filled while rendering content of ground cells. now sort the nodes based on their distance to viewer...
|
||||||
|
// TODO: move sorting for translucent phase, for opaque geometry render cells in initial order to reduce vbo switching
|
||||||
|
std::sort(
|
||||||
|
std::begin( m_cellqueue ),
|
||||||
|
std::end( m_cellqueue ),
|
||||||
|
[]( distancecell_pair const &Left, distancecell_pair const &Right ) {
|
||||||
|
return ( Left.first < Right.first ); } );
|
||||||
|
*/
|
||||||
|
// ...then render the opaque content of the visible cells.
|
||||||
|
Render( std::begin( m_cellqueue ), std::end( m_cellqueue ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::shadows:
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
// these render modes don't bother with lights
|
||||||
|
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
|
||||||
|
// they can also skip queue sorting, as they only deal with opaque geometry
|
||||||
|
// NOTE: there's benefit from rendering front-to-back, but is it significant enough? TODO: investigate
|
||||||
|
Render( std::begin( m_cellqueue ), std::end( m_cellqueue ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::reflections: {
|
||||||
|
// for the time being reflections render only terrain geometry
|
||||||
|
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::pickcontrols:
|
||||||
|
default: {
|
||||||
|
// no need to render anything ourside of the cab in control picking mode
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render( section_sequence::iterator First, section_sequence::iterator Last ) {
|
||||||
|
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color:
|
||||||
|
case rendermode::reflections: {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::shadows: {
|
||||||
|
// experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips'
|
||||||
|
::glDisable( GL_CULL_FACE );
|
||||||
|
break; }
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
// non-interactive scenery elements get neutral colour
|
||||||
|
::glColor3fv( glm::value_ptr( colors::none ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
while( First != Last ) {
|
||||||
|
|
||||||
|
auto *section = *First;
|
||||||
|
section->create_geometry();
|
||||||
|
|
||||||
|
// render shapes held by the section
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color:
|
||||||
|
case rendermode::reflections:
|
||||||
|
case rendermode::shadows:
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
if( false == section->m_shapes.empty() ) {
|
||||||
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
|
::glPushMatrix();
|
||||||
|
auto const originoffset { section->m_area.center - m_renderpass.camera.position() };
|
||||||
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
// render
|
||||||
|
#ifdef EU07_USE_DEBUG_CULLING
|
||||||
|
// debug
|
||||||
|
float const width = scene::EU07_SECTIONSIZE * 0.5f;
|
||||||
|
float const height = scene::EU07_SECTIONSIZE * 0.2f;
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
glColor3ub( 255, 128, 128 );
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glVertex3f( -width, height, width );
|
||||||
|
glVertex3f( -width, height, -width );
|
||||||
|
glVertex3f( width, height, -width );
|
||||||
|
glVertex3f( width, height, width );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glVertex3f( -width, 0, width );
|
||||||
|
glVertex3f( -width, 0, -width );
|
||||||
|
glVertex3f( width, 0, -width );
|
||||||
|
glVertex3f( width, 0, width );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINES );
|
||||||
|
glVertex3f( -width, height, width ); glVertex3f( -width, 0, width );
|
||||||
|
glVertex3f( -width, height, -width ); glVertex3f( -width, 0, -width );
|
||||||
|
glVertex3f( width, height, -width ); glVertex3f( width, 0, -width );
|
||||||
|
glVertex3f( width, height, width ); glVertex3f( width, 0, width );
|
||||||
|
glEnd();
|
||||||
|
glColor3ub( 255, 255, 255 );
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
#endif
|
||||||
|
// shapes
|
||||||
|
for( auto const &shape : section->m_shapes ) { Render( shape ); }
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::pickcontrols:
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the section's cells to the cell queue
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color:
|
||||||
|
case rendermode::shadows:
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
for( auto &cell : section->m_cells ) {
|
||||||
|
if( ( true == cell.m_active )
|
||||||
|
#ifdef EU07_USE_DEBUG_CULLING
|
||||||
|
&& ( m_worldcamera.camera.visible( cell.m_area ) ) ) {
|
||||||
|
#else
|
||||||
|
&& ( m_renderpass.camera.visible( cell.m_area ) ) ) {
|
||||||
|
#endif
|
||||||
|
// store visible cells with content as well as their current distance, for sorting later
|
||||||
|
m_cellqueue.emplace_back(
|
||||||
|
glm::length2( m_renderpass.camera.position() - cell.m_area.center ),
|
||||||
|
&cell );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
case rendermode::pickcontrols:
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// proceed to next section
|
||||||
|
++First;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::shadows: {
|
||||||
|
// restore standard face cull mode
|
||||||
|
::glEnable( GL_CULL_FACE );
|
||||||
|
break; }
|
||||||
|
default: {
|
||||||
|
break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator Last ) {
|
||||||
|
|
||||||
|
// cache initial iterator for the second sweep
|
||||||
|
auto first { First };
|
||||||
|
// first pass draws elements which we know are located in section banks, to reduce vbo switching
|
||||||
|
while( First != Last ) {
|
||||||
|
|
||||||
|
auto const *cell = First->second;
|
||||||
|
/*
|
||||||
|
// przeliczenia animacji torów w sektorze
|
||||||
|
Groundsubcell->RaAnimate( m_framestamp );
|
||||||
|
*/
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color: {
|
||||||
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
|
::glPushMatrix();
|
||||||
|
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
|
||||||
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
|
||||||
|
// render
|
||||||
|
#ifdef EU07_USE_DEBUG_CULLING
|
||||||
|
// debug
|
||||||
|
float const width = scene::EU07_CELLSIZE * 0.5f;
|
||||||
|
float const height = scene::EU07_CELLSIZE * 0.15f;
|
||||||
|
glDisable( GL_LIGHTING );
|
||||||
|
glDisable( GL_TEXTURE_2D );
|
||||||
|
glColor3ub( 255, 255, 0 );
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glVertex3f( -width, height, width );
|
||||||
|
glVertex3f( -width, height, -width );
|
||||||
|
glVertex3f( width, height, -width );
|
||||||
|
glVertex3f( width, height, width );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINE_LOOP );
|
||||||
|
glVertex3f( -width, 0, width );
|
||||||
|
glVertex3f( -width, 0, -width );
|
||||||
|
glVertex3f( width, 0, -width );
|
||||||
|
glVertex3f( width, 0, width );
|
||||||
|
glEnd();
|
||||||
|
glBegin( GL_LINES );
|
||||||
|
glVertex3f( -width, height, width ); glVertex3f( -width, 0, width );
|
||||||
|
glVertex3f( -width, height, -width ); glVertex3f( -width, 0, -width );
|
||||||
|
glVertex3f( width, height, -width ); glVertex3f( width, 0, -width );
|
||||||
|
glVertex3f( width, height, width ); glVertex3f( width, 0, width );
|
||||||
|
glEnd();
|
||||||
|
glColor3ub( 255, 255, 255 );
|
||||||
|
glEnable( GL_TEXTURE_2D );
|
||||||
|
glEnable( GL_LIGHTING );
|
||||||
|
#endif
|
||||||
|
// opaque non-instanced shapes
|
||||||
|
for( auto const &shape : cell->m_shapesopaque ) { Render( shape ); }
|
||||||
|
// tracks
|
||||||
|
// TODO: update after path node refactoring
|
||||||
|
for( auto *path : cell->m_paths ) { Render( path ); }
|
||||||
|
// TODO: add other content types
|
||||||
|
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::shadows: {
|
||||||
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
|
::glPushMatrix();
|
||||||
|
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
|
||||||
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
|
||||||
|
// render
|
||||||
|
// opaque non-instanced shapes
|
||||||
|
for( auto const &shape : cell->m_shapesopaque ) { Render( shape ); }
|
||||||
|
// TODO: add other content types
|
||||||
|
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
// same procedure like with regular render, but editor-enabled nodes receive custom colour used for picking
|
||||||
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
|
::glPushMatrix();
|
||||||
|
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
|
||||||
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
// render
|
||||||
|
// opaque non-instanced shapes
|
||||||
|
for( auto const &shape : cell->m_shapesopaque ) { Render( shape ); }
|
||||||
|
// tracks
|
||||||
|
// TODO: add path to the node picking list
|
||||||
|
for( auto *path : cell->m_paths ) { Render( path ); }
|
||||||
|
// TODO: add other content types
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
case rendermode::pickcontrols:
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++First;
|
||||||
|
}
|
||||||
|
// second pass draws elements with their own vbos
|
||||||
|
while( first != Last ) {
|
||||||
|
|
||||||
|
auto const *cell = first->second;
|
||||||
|
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color:
|
||||||
|
case rendermode::shadows:
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
// render
|
||||||
|
// opaque parts of instanced models
|
||||||
|
for( auto *instance : cell->m_instancesopaque ) { Render( instance ); }
|
||||||
|
// TODO: add remaining content types
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
case rendermode::pickcontrols:
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render( scene::shape_node const &Shape ) {
|
||||||
|
|
||||||
|
auto const &data { Shape.data() };
|
||||||
|
// setup
|
||||||
|
Bind_Material( data.material );
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::color:
|
||||||
|
case rendermode::reflections: {
|
||||||
|
::glColor3fv( glm::value_ptr( data.lighting.diffuse ) );
|
||||||
|
/*
|
||||||
|
// NOTE: ambient component is set by diffuse component
|
||||||
|
// NOTE: for the time being non-instanced shapes are rendered without specular component due to wrong/arbitrary values set in legacy scenarios
|
||||||
|
// TBD, TODO: find a way to resolve this with the least amount of tears?
|
||||||
|
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( data.lighting.specular * Global::DayLight.specular.a * m_specularopaquescalefactor ) );
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// pick modes are painted with custom colours, and shadow pass doesn't use any
|
||||||
|
case rendermode::shadows:
|
||||||
|
case rendermode::pickscenery:
|
||||||
|
case rendermode::pickcontrols:
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// render
|
||||||
|
m_geometry.draw( data.geometry );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render( TAnimModel *Instance ) {
|
||||||
|
|
||||||
|
double distancesquared;
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::shadows: {
|
||||||
|
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
|
||||||
|
distancesquared = SquareMagnitude( ( Instance->m_location - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
distancesquared = SquareMagnitude( ( Instance->m_location - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( distancesquared < Instance->m_rangesquaredmin )
|
||||||
|
|| ( distancesquared >= Instance->m_rangesquaredmax ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// TODO: enable adding items to the picking list
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::pickscenery: {
|
||||||
|
// add the node to the pick list
|
||||||
|
m_picksceneryitems.emplace_back( Node );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Instance->RaAnimate( m_framestamp ); // jednorazowe przeliczenie animacji
|
||||||
|
Instance->RaPrepare();
|
||||||
|
if( Instance->pModel ) {
|
||||||
|
// renderowanie rekurencyjne submodeli
|
||||||
|
Render(
|
||||||
|
Instance->pModel,
|
||||||
|
Instance->Material(),
|
||||||
|
distancesquared,
|
||||||
|
Instance->m_location - m_renderpass.camera.position(),
|
||||||
|
Instance->vAngle );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
opengl_renderer::Render( TGroundNode *Node ) {
|
opengl_renderer::Render( TGroundNode *Node ) {
|
||||||
@@ -2272,6 +2692,9 @@ opengl_renderer::Render( TTrack *Track ) {
|
|||||||
&& ( Track->m_material2 == 0 ) ) {
|
&& ( Track->m_material2 == 0 ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if( false == Track->m_visible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch( m_renderpass.draw_mode ) {
|
switch( m_renderpass.draw_mode ) {
|
||||||
case rendermode::color:
|
case rendermode::color:
|
||||||
@@ -2311,7 +2734,7 @@ void
|
|||||||
opengl_renderer::Render( TMemCell *Memcell ) {
|
opengl_renderer::Render( TMemCell *Memcell ) {
|
||||||
|
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const position = Memcell->Position() - m_renderpass.camera.position();
|
auto const position = Memcell->location() - m_renderpass.camera.position();
|
||||||
::glTranslated( position.x, position.y + 0.5, position.z );
|
::glTranslated( position.x, position.y + 0.5, position.z );
|
||||||
|
|
||||||
switch( m_renderpass.draw_mode ) {
|
switch( m_renderpass.draw_mode ) {
|
||||||
@@ -2342,27 +2765,28 @@ opengl_renderer::Render( TMemCell *Memcell ) {
|
|||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
bool
|
bool
|
||||||
opengl_renderer::Render_Alpha( TGround *Ground ) {
|
opengl_renderer::Render_Alpha( TGround *Ground ) {
|
||||||
|
|
||||||
TGroundNode *node;
|
TGroundNode *node;
|
||||||
TSubRect *tmp;
|
TSubRect *tmp;
|
||||||
// Ra: renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
|
// Ra: renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
|
||||||
for( auto subcellpair = std::rbegin( m_drawqueue ); subcellpair != std::rend( m_drawqueue ); ++subcellpair ) {
|
for( auto subcellpair = std::rbegin( m_cellqueue ); subcellpair != std::rend( m_cellqueue ); ++subcellpair ) {
|
||||||
// przezroczyste trójkąty w oddzielnym cyklu przed modelami
|
// przezroczyste trójkąty w oddzielnym cyklu przed modelami
|
||||||
tmp = subcellpair->second;
|
tmp = subcellpair->second;
|
||||||
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
||||||
Render_Alpha( node );
|
Render_Alpha( node );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( auto subcellpair = std::rbegin( m_drawqueue ); subcellpair != std::rend( m_drawqueue ); ++subcellpair )
|
for( auto subcellpair = std::rbegin( m_cellqueue ); subcellpair != std::rend( m_cellqueue ); ++subcellpair )
|
||||||
{ // renderowanie przezroczystych modeli oraz pojazdów
|
{ // renderowanie przezroczystych modeli oraz pojazdów
|
||||||
Render_Alpha( subcellpair->second );
|
Render_Alpha( subcellpair->second );
|
||||||
}
|
}
|
||||||
|
|
||||||
::glDisable( GL_LIGHTING ); // linie nie powinny świecić
|
::glDisable( GL_LIGHTING ); // linie nie powinny świecić
|
||||||
|
|
||||||
for( auto subcellpair = std::rbegin( m_drawqueue ); subcellpair != std::rend( m_drawqueue ); ++subcellpair ) {
|
for( auto subcellpair = std::rbegin( m_cellqueue ); subcellpair != std::rend( m_cellqueue ); ++subcellpair ) {
|
||||||
// druty na końcu, żeby się nie robiły białe plamy na tle lasu
|
// druty na końcu, żeby się nie robiły białe plamy na tle lasu
|
||||||
tmp = subcellpair->second;
|
tmp = subcellpair->second;
|
||||||
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||||
@@ -2391,7 +2815,177 @@ opengl_renderer::Render_Alpha( TSubRect *Groundsubcell ) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
opengl_renderer::Render_Alpha( scene::basic_region &Region ) {
|
||||||
|
|
||||||
|
// sort the nodes based on their distance to viewer
|
||||||
|
std::sort(
|
||||||
|
std::begin( m_cellqueue ),
|
||||||
|
std::end( m_cellqueue ),
|
||||||
|
[]( distancecell_pair const &Left, distancecell_pair const &Right ) {
|
||||||
|
return ( Left.first ) < ( Right.first ); } );
|
||||||
|
|
||||||
|
Render_Alpha( std::rbegin( m_cellqueue ), std::rend( m_cellqueue ) );
|
||||||
|
/*
|
||||||
|
::glDisable( GL_LIGHTING ); // linie nie powinny świecić
|
||||||
|
for( auto subcellpair = std::rbegin( m_cellqueue ); subcellpair != std::rend( m_cellqueue ); ++subcellpair ) {
|
||||||
|
// druty na końcu, żeby się nie robiły białe plamy na tle lasu
|
||||||
|
tmp = subcellpair->second;
|
||||||
|
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||||
|
Render_Alpha( node );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::glEnable( GL_LIGHTING );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_sequence::reverse_iterator Last ) {
|
||||||
|
|
||||||
|
// first pass draws elements which we know are located in section banks, to reduce vbo switching
|
||||||
|
{
|
||||||
|
auto first { First };
|
||||||
|
while( first != Last ) {
|
||||||
|
|
||||||
|
auto const *cell = first->second;
|
||||||
|
|
||||||
|
if( false == cell->m_shapestranslucent.empty() ) {
|
||||||
|
// since all shapes of the cell share center point we can optimize out a few calls here
|
||||||
|
::glPushMatrix();
|
||||||
|
auto const originoffset{ cell->m_area.center - m_renderpass.camera.position() };
|
||||||
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
// render
|
||||||
|
// NOTE: we can reuse the method used to draw opaque geometry
|
||||||
|
for( auto const &shape : cell->m_shapestranslucent ) { Render( shape ); }
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// second pass draws elements with their own vbos
|
||||||
|
{
|
||||||
|
auto first { First };
|
||||||
|
while( first != Last ) {
|
||||||
|
|
||||||
|
auto const *cell = first->second;
|
||||||
|
|
||||||
|
// translucent parts of instanced models
|
||||||
|
for( auto *instance : cell->m_instancetranslucent ) { Render_Alpha( instance ); }
|
||||||
|
// TODO: add remaining content types
|
||||||
|
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// third pass draws the wires;
|
||||||
|
// wires use section vbos, but for the time being we want to draw them at the very end
|
||||||
|
{
|
||||||
|
auto first{ First };
|
||||||
|
while( first != Last ) {
|
||||||
|
|
||||||
|
auto const *cell = first->second;
|
||||||
|
// TODO: include lines here
|
||||||
|
if( false == cell->m_traction.empty() ) {
|
||||||
|
// since all shapes of the cell share center point we can optimize out a few calls here
|
||||||
|
::glPushMatrix();
|
||||||
|
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
|
||||||
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
if( !Global::bSmoothTraction ) {
|
||||||
|
// na liniach kiepsko wygląda - robi gradient
|
||||||
|
::glDisable( GL_LINE_SMOOTH );
|
||||||
|
}
|
||||||
|
Bind_Material( null_handle );
|
||||||
|
// render
|
||||||
|
for( auto *traction : cell->m_traction ) { Render_Alpha( traction ); }
|
||||||
|
// post-render cleanup
|
||||||
|
::glLineWidth( 1.0 );
|
||||||
|
if( !Global::bSmoothTraction ) {
|
||||||
|
::glEnable( GL_LINE_SMOOTH );
|
||||||
|
}
|
||||||
|
::glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render_Alpha( TAnimModel *Instance ) {
|
||||||
|
|
||||||
|
double distancesquared;
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::shadows: {
|
||||||
|
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
|
||||||
|
distancesquared = SquareMagnitude( ( Instance->m_location - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
distancesquared = SquareMagnitude( ( Instance->m_location - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( distancesquared < Instance->m_rangesquaredmin )
|
||||||
|
|| ( distancesquared >= Instance->m_rangesquaredmax ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance->RaPrepare();
|
||||||
|
if( Instance->pModel ) {
|
||||||
|
// renderowanie rekurencyjne submodeli
|
||||||
|
Render_Alpha(
|
||||||
|
Instance->pModel,
|
||||||
|
Instance->Material(),
|
||||||
|
distancesquared,
|
||||||
|
Instance->m_location - m_renderpass.camera.position(),
|
||||||
|
Instance->vAngle );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opengl_renderer::Render_Alpha( TTraction *Traction ) {
|
||||||
|
|
||||||
|
double distancesquared;
|
||||||
|
switch( m_renderpass.draw_mode ) {
|
||||||
|
case rendermode::shadows: {
|
||||||
|
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
|
||||||
|
distancesquared = SquareMagnitude( ( Traction->m_location - Global::pCameraPosition ) / Global::ZoomFactor ) / Global::fDistanceFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
distancesquared = SquareMagnitude( ( Traction->m_location - m_renderpass.camera.position() ) / Global::ZoomFactor ) / Global::fDistanceFactor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( distancesquared < Traction->m_rangesquaredmin )
|
||||||
|
|| ( distancesquared >= Traction->m_rangesquaredmax ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( false == Traction->m_visible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// rysuj jesli sa druty i nie zerwana
|
||||||
|
if( ( Traction->Wires == 0 )
|
||||||
|
|| ( true == TestFlag( Traction->DamageFlag, 128 ) ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// setup
|
||||||
|
float const linealpha = static_cast<float>(
|
||||||
|
std::min(
|
||||||
|
1.25,
|
||||||
|
5000 * Traction->WireThickness / ( distancesquared + 1.0 ) ) ); // zbyt grube nie są dobre
|
||||||
|
::glLineWidth( linealpha );
|
||||||
|
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||||
|
auto const color { Traction->wire_color() };
|
||||||
|
::glColor4f( color.r, color.g, color.b, linealpha );
|
||||||
|
|
||||||
|
// render
|
||||||
|
m_geometry.draw( Traction->m_geometry );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
bool
|
bool
|
||||||
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||||
|
|
||||||
@@ -2857,6 +3451,8 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
|||||||
Render_Alpha( Submodel->Next );
|
Render_Alpha( Submodel->Next );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// utility methods
|
// utility methods
|
||||||
TSubModel const *
|
TSubModel const *
|
||||||
opengl_renderer::Update_Pick_Control() {
|
opengl_renderer::Update_Pick_Control() {
|
||||||
|
|||||||
45
renderer.h
45
renderer.h
@@ -15,12 +15,14 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "lightarray.h"
|
#include "lightarray.h"
|
||||||
#include "dumb3d.h"
|
#include "dumb3d.h"
|
||||||
#include "frustum.h"
|
#include "frustum.h"
|
||||||
|
#include "scene.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "memcell.h"
|
#include "memcell.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
|
||||||
@@ -225,7 +227,13 @@ private:
|
|||||||
diffuse
|
diffuse
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::pair< double, TSubRect * > distancesubcell_pair;
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
using distancesubcell_pair = std::pair< double, TSubRect * >;
|
||||||
|
#else
|
||||||
|
using section_sequence = std::vector<scene::basic_section *>;
|
||||||
|
using distancecell_pair = std::pair<double, scene::basic_cell *>;
|
||||||
|
using cell_sequence = std::vector<distancecell_pair>;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct renderpass_config {
|
struct renderpass_config {
|
||||||
|
|
||||||
@@ -266,12 +274,25 @@ private:
|
|||||||
Render_reflections();
|
Render_reflections();
|
||||||
bool
|
bool
|
||||||
Render( world_environment *Environment );
|
Render( world_environment *Environment );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
bool
|
bool
|
||||||
Render( TGround *Ground );
|
Render( TGround *Ground );
|
||||||
bool
|
bool
|
||||||
Render( TGroundRect *Groundcell );
|
Render( TGroundRect *Groundcell );
|
||||||
bool
|
bool
|
||||||
Render( TSubRect *Groundsubcell );
|
Render( TSubRect *Groundsubcell );
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
Render( scene::basic_region &Region );
|
||||||
|
void
|
||||||
|
Render( section_sequence::iterator First, section_sequence::iterator Last );
|
||||||
|
void
|
||||||
|
Render( cell_sequence::iterator First, cell_sequence::iterator Last );
|
||||||
|
void
|
||||||
|
Render( scene::shape_node const &Shape );
|
||||||
|
void
|
||||||
|
Render( TAnimModel *Instance );
|
||||||
|
#endif
|
||||||
bool
|
bool
|
||||||
Render( TGroundNode *Node );
|
Render( TGroundNode *Node );
|
||||||
bool
|
bool
|
||||||
@@ -288,10 +309,21 @@ private:
|
|||||||
Render_cab( TDynamicObject *Dynamic, bool const Alpha = false );
|
Render_cab( TDynamicObject *Dynamic, bool const Alpha = false );
|
||||||
void
|
void
|
||||||
Render( TMemCell *Memcell );
|
Render( TMemCell *Memcell );
|
||||||
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
bool
|
bool
|
||||||
Render_Alpha( TGround *Ground );
|
Render_Alpha( TGround *Ground );
|
||||||
bool
|
bool
|
||||||
Render_Alpha( TSubRect *Groundsubcell );
|
Render_Alpha( TSubRect *Groundsubcell );
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
Render_Alpha( scene::basic_region &Region );
|
||||||
|
void
|
||||||
|
Render_Alpha( cell_sequence::reverse_iterator First, cell_sequence::reverse_iterator Last );
|
||||||
|
void
|
||||||
|
Render_Alpha( TAnimModel *Instance );
|
||||||
|
void
|
||||||
|
Render_Alpha( TTraction *Traction );
|
||||||
|
#endif
|
||||||
bool
|
bool
|
||||||
Render_Alpha( TGroundNode *Node );
|
Render_Alpha( TGroundNode *Node );
|
||||||
bool
|
bool
|
||||||
@@ -361,13 +393,18 @@ private:
|
|||||||
std::string m_pickdebuginfo;
|
std::string m_pickdebuginfo;
|
||||||
|
|
||||||
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
|
#ifdef EU07_USE_OLD_GROUNDCODE
|
||||||
|
std::vector<distancesubcell_pair> m_cellqueue; // list of subcells to be drawn in current render pass
|
||||||
|
#else
|
||||||
|
section_sequence m_sectionqueue; // list of sections in current render pass
|
||||||
|
cell_sequence m_cellqueue;
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<TGroundNode const *> m_picksceneryitems;
|
std::vector<TGroundNode const *> m_picksceneryitems;
|
||||||
std::vector<TSubModel const *> m_pickcontrolsitems;
|
std::vector<TSubModel const *> m_pickcontrolsitems;
|
||||||
|
|||||||
579
scene.cpp
Normal file
579
scene.cpp
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
/*
|
||||||
|
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 "scene.h"
|
||||||
|
|
||||||
|
#include "renderer.h"
|
||||||
|
#include "logs.h"
|
||||||
|
|
||||||
|
namespace scene {
|
||||||
|
|
||||||
|
// adds provided shape to the cell
|
||||||
|
void
|
||||||
|
basic_cell::insert( shape_node Shape ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
auto const &shapedata { Shape.data() };
|
||||||
|
auto &shapes = (
|
||||||
|
shapedata.translucent ?
|
||||||
|
m_shapestranslucent :
|
||||||
|
m_shapesopaque );
|
||||||
|
for( auto &targetshape : shapes ) {
|
||||||
|
// try to merge shapes with matching view ranges...
|
||||||
|
auto const &targetshapedata { targetshape.data() };
|
||||||
|
if( ( shapedata.rangesquared_min == targetshapedata.rangesquared_min )
|
||||||
|
&& ( shapedata.rangesquared_max == targetshapedata.rangesquared_max )
|
||||||
|
// ...and located close to each other (within arbitrary limit of 25m)
|
||||||
|
&& ( glm::length( shapedata.area.center - targetshapedata.area.center ) < 25.0 ) ) {
|
||||||
|
|
||||||
|
if( true == targetshape.merge( Shape ) ) {
|
||||||
|
// if the shape was merged there's nothing left to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise add the shape to the relevant list
|
||||||
|
Shape.origin( m_area.center );
|
||||||
|
shapes.emplace_back( Shape );
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided path to the cell
|
||||||
|
void
|
||||||
|
basic_cell::insert( TTrack *Path ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
// TODO: add animation hook
|
||||||
|
Path->origin( m_area.center );
|
||||||
|
m_paths.emplace_back( Path );
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided traction piece to the cell
|
||||||
|
void
|
||||||
|
basic_cell::insert( TTraction *Traction ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
Traction->origin( m_area.center );
|
||||||
|
m_traction.emplace_back( Traction );
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided model instance to the cell
|
||||||
|
void
|
||||||
|
basic_cell::insert( TAnimModel *Instance ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
auto const flags = Instance->Flags();
|
||||||
|
auto alpha =
|
||||||
|
( Instance->Material() != nullptr ?
|
||||||
|
Instance->Material()->textures_alpha :
|
||||||
|
0x30300030 );
|
||||||
|
|
||||||
|
// assign model to appropriate render phases
|
||||||
|
if( alpha & flags & 0x2F2F002F ) {
|
||||||
|
// translucent pieces
|
||||||
|
m_instancetranslucent.emplace_back( Instance );
|
||||||
|
}
|
||||||
|
alpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste
|
||||||
|
if( alpha & flags & 0x1F1F001F ) {
|
||||||
|
// opaque pieces
|
||||||
|
m_instancesopaque.emplace_back( Instance );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates renderable version of held non-instanced geometry
|
||||||
|
void
|
||||||
|
basic_cell::create_geometry( geometrybank_handle const &Bank ) {
|
||||||
|
|
||||||
|
if( false == m_active ) { return; } // nothing to do here
|
||||||
|
|
||||||
|
for( auto &shape : m_shapesopaque ) { shape.create_geometry( Bank ); }
|
||||||
|
for( auto &shape : m_shapestranslucent ) { shape.create_geometry( Bank ); }
|
||||||
|
#ifndef EU07_USE_OLD_GROUNDCODE
|
||||||
|
for( auto *path : m_paths ) { path->create_geometry( Bank ); }
|
||||||
|
for( auto *traction : m_traction ) { traction->create_geometry( Bank ); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets center point of the section
|
||||||
|
void
|
||||||
|
basic_cell::center( glm::dvec3 Center ) {
|
||||||
|
|
||||||
|
m_area.center = Center;
|
||||||
|
// NOTE: we should also update origin point for the contained nodes, but in practice we can skip this
|
||||||
|
// as all nodes will be added only after the proper center point was set, and won't change
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// adds provided shape to the section
|
||||||
|
void
|
||||||
|
basic_section::insert( shape_node Shape ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
|
||||||
|
auto const &shapedata = Shape.data();
|
||||||
|
if( ( true == shapedata.translucent )
|
||||||
|
|| ( shapedata.rangesquared_max <= 90000.0 )
|
||||||
|
|| ( shapedata.rangesquared_min > 0.0 ) ) {
|
||||||
|
// small, translucent or not always visible shapes are placed in the sub-cells
|
||||||
|
cell( shapedata.area.center ).insert( Shape );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// large, opaque shapes are placed on section level
|
||||||
|
for( auto &shape : m_shapes ) {
|
||||||
|
// check first if the shape can't be merged with one of the shapes already present in the section
|
||||||
|
if( true == shape.merge( Shape ) ) {
|
||||||
|
// if the shape was merged there's nothing left to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise add the shape to the section's list
|
||||||
|
Shape.origin( m_area.center );
|
||||||
|
m_shapes.emplace_back( Shape );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided path to the section
|
||||||
|
void
|
||||||
|
basic_section::insert( TTrack *Path ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
// pass the node to the appropriate partitioning cell
|
||||||
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
|
cell( Path->location() ).insert( Path );
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided path to the section
|
||||||
|
void
|
||||||
|
basic_section::insert( TTraction *Traction ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
// pass the node to the appropriate partitioning cell
|
||||||
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
|
cell( Traction->location() ).insert( Traction );
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds provided model instance to the section
|
||||||
|
void
|
||||||
|
basic_section::insert( TAnimModel *Instance ) {
|
||||||
|
|
||||||
|
m_active = true;
|
||||||
|
// pass the node to the appropriate partitioning cell
|
||||||
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
|
cell( Instance->location() ).insert( Instance );
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets center point of the section
|
||||||
|
void
|
||||||
|
basic_section::center( glm::dvec3 Center ) {
|
||||||
|
|
||||||
|
m_area.center = Center;
|
||||||
|
// set accordingly center points of the section's partitioning cells
|
||||||
|
// NOTE: we should also update origin point for the contained nodes, but in practice we can skip this
|
||||||
|
// as all nodes will be added only after the proper center point was set, and won't change
|
||||||
|
auto const centeroffset = -( EU07_SECTIONSIZE / EU07_CELLSIZE / 2 * EU07_CELLSIZE ) + EU07_CELLSIZE / 2;
|
||||||
|
glm::dvec3 sectioncornercenter { m_area.center + glm::dvec3{ centeroffset, 0, centeroffset } };
|
||||||
|
auto row { 0 }, column { 0 };
|
||||||
|
for( auto &cell : m_cells ) {
|
||||||
|
cell.center( sectioncornercenter + glm::dvec3{ column * EU07_CELLSIZE, 0.0, row * EU07_CELLSIZE } );
|
||||||
|
if( ++column >= EU07_SECTIONSIZE / EU07_CELLSIZE ) {
|
||||||
|
++row;
|
||||||
|
column = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates renderable version of held non-instanced geometry
|
||||||
|
void
|
||||||
|
basic_section::create_geometry() {
|
||||||
|
|
||||||
|
if( true == m_geometrycreated ) { return; }
|
||||||
|
else {
|
||||||
|
// mark it done for future checks
|
||||||
|
m_geometrycreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( false == m_active ) { return; } // nothing to do here
|
||||||
|
|
||||||
|
// since sections can be empty, we're doing lazy initialization of the geometry bank, when something may actually use it
|
||||||
|
if( m_geometrybank == null_handle ) {
|
||||||
|
m_geometrybank = GfxRenderer.Create_Bank();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( auto &shape : m_shapes ) {
|
||||||
|
shape.create_geometry( m_geometrybank );
|
||||||
|
}
|
||||||
|
for( auto &cell : m_cells ) {
|
||||||
|
cell.create_geometry( m_geometrybank );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// provides access to section enclosing specified point
|
||||||
|
basic_cell &
|
||||||
|
basic_section::cell( glm::dvec3 const &Location ) {
|
||||||
|
|
||||||
|
auto const column = static_cast<int>( std::floor( ( Location.x - ( m_area.center.x - EU07_SECTIONSIZE / 2 ) ) / EU07_CELLSIZE ) );
|
||||||
|
auto const row = static_cast<int>( std::floor( ( Location.z - ( m_area.center.z - EU07_SECTIONSIZE / 2 ) ) / EU07_CELLSIZE ) );
|
||||||
|
|
||||||
|
return
|
||||||
|
m_cells[
|
||||||
|
clamp( row, 0, ( EU07_SECTIONSIZE / EU07_CELLSIZE ) - 1 ) * ( EU07_SECTIONSIZE / EU07_CELLSIZE )
|
||||||
|
+ clamp( column, 0, ( EU07_SECTIONSIZE / EU07_CELLSIZE ) - 1 ) ] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
basic_region::basic_region() {
|
||||||
|
|
||||||
|
// initialize centers of sections:
|
||||||
|
// calculate center of 'top left' region section...
|
||||||
|
auto const centeroffset = -( EU07_REGIONSIDESECTIONCOUNT / 2 * EU07_SECTIONSIZE ) + EU07_SECTIONSIZE / 2;
|
||||||
|
glm::dvec3 regioncornercenter { centeroffset, 0, centeroffset };
|
||||||
|
auto row { 0 }, column { 0 };
|
||||||
|
// ...move through section array assigning centers left to right, front/top to back/bottom
|
||||||
|
for( auto §ion : m_sections ) {
|
||||||
|
section.center( regioncornercenter + glm::dvec3{ column * EU07_SECTIONSIZE, 0.0, row * EU07_SECTIONSIZE } );
|
||||||
|
if( ++column >= EU07_REGIONSIDESECTIONCOUNT ) {
|
||||||
|
++row;
|
||||||
|
column = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
basic_region::insert_shape( shape_node Shape, scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// shape might need to be split into smaller pieces, so we create list of nodes instead of just single one
|
||||||
|
// using deque so we can do single pass iterating and addding generated pieces without invalidating anything
|
||||||
|
std::deque<shape_node> shapes { Shape };
|
||||||
|
auto &shape = shapes.front();
|
||||||
|
if( shape.m_data.vertices.empty() ) { return; }
|
||||||
|
|
||||||
|
// adjust input if necessary:
|
||||||
|
if( Scratchpad.location_rotation != glm::vec3( 0, 0, 0 ) ) {
|
||||||
|
// rotate...
|
||||||
|
auto const rotation = glm::radians( Scratchpad.location_rotation );
|
||||||
|
for( auto &vertex : shape.m_data.vertices ) {
|
||||||
|
vertex.position = glm::rotateZ<double>( vertex.position, rotation.z );
|
||||||
|
vertex.position = glm::rotateX<double>( vertex.position, rotation.x );
|
||||||
|
vertex.position = glm::rotateY<double>( vertex.position, rotation.y );
|
||||||
|
vertex.normal = glm::rotateZ( vertex.normal, rotation.z );
|
||||||
|
vertex.normal = glm::rotateX( vertex.normal, rotation.x );
|
||||||
|
vertex.normal = glm::rotateY( vertex.normal, rotation.y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( false == Scratchpad.location_offset.empty() )
|
||||||
|
&& ( Scratchpad.location_offset.top() != glm::dvec3( 0, 0, 0 ) ) ) {
|
||||||
|
// ...and move
|
||||||
|
auto const offset = Scratchpad.location_offset.top();
|
||||||
|
for( auto &vertex : shape.m_data.vertices ) {
|
||||||
|
vertex.position += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// calculate bounding area
|
||||||
|
for( auto const &vertex : shape.m_data.vertices ) {
|
||||||
|
shape.m_data.area.center += vertex.position;
|
||||||
|
}
|
||||||
|
shape.m_data.area.center /= shape.m_data.vertices.size();
|
||||||
|
// trim the shape if needed. trimmed parts will be added to list as separate nodes
|
||||||
|
for( std::size_t index = 0; index < shapes.size(); ++index ) {
|
||||||
|
while( true == RaTriangleDivider( shapes[ index ], shapes ) ) {
|
||||||
|
; // all work is done during expression check
|
||||||
|
}
|
||||||
|
// with the trimming done we can calculate shape's bounding radius
|
||||||
|
shape.compute_radius();
|
||||||
|
}
|
||||||
|
// move the data into appropriate section(s)
|
||||||
|
for( auto &shape : shapes ) {
|
||||||
|
|
||||||
|
if( point_inside( shape.m_data.area.center ) ) {
|
||||||
|
// NOTE: nodes placed outside of region boundaries are discarded
|
||||||
|
section( shape.m_data.area.center ).insert( shape );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog(
|
||||||
|
"Bad scenario: shape node" + (
|
||||||
|
shape.m_name.empty() ?
|
||||||
|
"" :
|
||||||
|
" \"" + shape.m_name + "\"" )
|
||||||
|
+ " placed in location outside region bounds (" + to_string( shape.m_data.area.center ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inserts provided track in the region
|
||||||
|
void
|
||||||
|
basic_region::insert_path( TTrack *Path, scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
|
auto center = Path->location();
|
||||||
|
|
||||||
|
if( point_inside( center ) ) {
|
||||||
|
// NOTE: nodes placed outside of region boundaries are discarded
|
||||||
|
section( center ).insert( Path );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// tracks are guaranteed to hava a name so we can skip the check
|
||||||
|
ErrorLog( "Bad scenario: track node \"" + Path->name() + "\" placed in location outside region bounds (" + to_string( center ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inserts provided track in the region
|
||||||
|
void
|
||||||
|
basic_region::insert_traction( TTraction *Traction, scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
|
auto center = Traction->location();
|
||||||
|
|
||||||
|
if( point_inside( center ) ) {
|
||||||
|
// NOTE: nodes placed outside of region boundaries are discarded
|
||||||
|
section( center ).insert( Traction );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// tracks are guaranteed to hava a name so we can skip the check
|
||||||
|
ErrorLog( "Bad scenario: traction node \"" + Traction->name() + "\" placed in location outside region bounds (" + to_string( center ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inserts provided instance of 3d model in the region
|
||||||
|
void
|
||||||
|
basic_region::insert_instance( TAnimModel *Instance, scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// NOTE: bounding area isn't present/filled until track class and wrapper refactoring is done
|
||||||
|
auto center = Instance->location();
|
||||||
|
|
||||||
|
if( point_inside( center ) ) {
|
||||||
|
// NOTE: nodes placed outside of region boundaries are discarded
|
||||||
|
section( center ).insert( Instance );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// tracks are guaranteed to hava a name so we can skip the check
|
||||||
|
ErrorLog( "Bad scenario: model node \"" + Instance->name() + "\" placed in location outside region bounds (" + to_string( center ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks whether specified point is within boundaries of the region
|
||||||
|
bool
|
||||||
|
basic_region::point_inside( glm::dvec3 const &Location ) {
|
||||||
|
|
||||||
|
double const regionboundary = EU07_REGIONSIDESECTIONCOUNT / 2 * EU07_SECTIONSIZE;
|
||||||
|
return ( ( Location.x > -regionboundary ) && ( Location.x < regionboundary )
|
||||||
|
&& ( Location.z > -regionboundary ) && ( Location.z < regionboundary ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// trims provided shape to fit into a section, adds trimmed part at the end of provided list
|
||||||
|
// NOTE: legacy function. TBD, TODO: clean it up?
|
||||||
|
bool
|
||||||
|
basic_region::RaTriangleDivider( shape_node &Shape, std::deque<shape_node> &Shapes ) {
|
||||||
|
|
||||||
|
if( Shape.m_data.vertices.size() != 3 ) {
|
||||||
|
// tylko gdy jeden trójkąt
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const margin { 200.0 };
|
||||||
|
auto x0 = EU07_SECTIONSIZE * std::floor( 0.001 * Shape.m_data.area.center.x ) - margin;
|
||||||
|
auto x1 = x0 + EU07_SECTIONSIZE + margin * 2;
|
||||||
|
auto z0 = EU07_SECTIONSIZE * std::floor( 0.001 * Shape.m_data.area.center.z ) - margin;
|
||||||
|
auto z1 = z0 + EU07_SECTIONSIZE + margin * 2;
|
||||||
|
|
||||||
|
if( ( Shape.m_data.vertices[ 0 ].position.x >= x0 ) && ( Shape.m_data.vertices[ 0 ].position.x <= x1 )
|
||||||
|
&& ( Shape.m_data.vertices[ 0 ].position.z >= z0 ) && ( Shape.m_data.vertices[ 0 ].position.z <= z1 )
|
||||||
|
&& ( Shape.m_data.vertices[ 1 ].position.x >= x0 ) && ( Shape.m_data.vertices[ 1 ].position.x <= x1 )
|
||||||
|
&& ( Shape.m_data.vertices[ 1 ].position.z >= z0 ) && ( Shape.m_data.vertices[ 1 ].position.z <= z1 )
|
||||||
|
&& ( Shape.m_data.vertices[ 2 ].position.x >= x0 ) && ( Shape.m_data.vertices[ 2 ].position.x <= x1 )
|
||||||
|
&& ( Shape.m_data.vertices[ 2 ].position.z >= z0 ) && ( Shape.m_data.vertices[ 2 ].position.z <= z1 ) ) {
|
||||||
|
// trójkąt wystający mniej niż 200m z kw. kilometrowego jest do przyjęcia
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Ra: przerobić na dzielenie na 2 trójkąty, podział w przecięciu z siatką kilometrową
|
||||||
|
// Ra: i z rekurencją będzie dzielić trzy trójkąty, jeśli będzie taka potrzeba
|
||||||
|
int divide { -1 }; // bok do podzielenia: 0=AB, 1=BC, 2=CA; +4=podział po OZ; +8 na x1/z1
|
||||||
|
double
|
||||||
|
min { 0.0 },
|
||||||
|
mul; // jeśli przechodzi przez oś, iloczyn będzie ujemny
|
||||||
|
x0 += margin;
|
||||||
|
x1 -= margin; // przestawienie na siatkę
|
||||||
|
z0 += margin;
|
||||||
|
z1 -= margin;
|
||||||
|
// AB na wschodzie
|
||||||
|
mul = ( Shape.m_data.vertices[ 0 ].position.x - x0 ) * ( Shape.m_data.vertices[ 1 ].position.x - x0 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 0;
|
||||||
|
}
|
||||||
|
// BC na wschodzie
|
||||||
|
mul = ( Shape.m_data.vertices[ 1 ].position.x - x0 ) * ( Shape.m_data.vertices[ 2 ].position.x - x0 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 1;
|
||||||
|
}
|
||||||
|
// CA na wschodzie
|
||||||
|
mul = ( Shape.m_data.vertices[ 2 ].position.x - x0 ) * ( Shape.m_data.vertices[ 0 ].position.x - x0 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 2;
|
||||||
|
}
|
||||||
|
// AB na zachodzie
|
||||||
|
mul = ( Shape.m_data.vertices[ 0 ].position.x - x1 ) * ( Shape.m_data.vertices[ 1 ].position.x - x1 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 8;
|
||||||
|
}
|
||||||
|
// BC na zachodzie
|
||||||
|
mul = ( Shape.m_data.vertices[ 1 ].position.x - x1 ) * ( Shape.m_data.vertices[ 2 ].position.x - x1 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 9;
|
||||||
|
}
|
||||||
|
// CA na zachodzie
|
||||||
|
mul = ( Shape.m_data.vertices[ 2 ].position.x - x1 ) * ( Shape.m_data.vertices[ 0 ].position.x - x1 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 10;
|
||||||
|
}
|
||||||
|
// AB na południu
|
||||||
|
mul = ( Shape.m_data.vertices[ 0 ].position.z - z0 ) * ( Shape.m_data.vertices[ 1 ].position.z - z0 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 4;
|
||||||
|
}
|
||||||
|
// BC na południu
|
||||||
|
mul = ( Shape.m_data.vertices[ 1 ].position.z - z0 ) * ( Shape.m_data.vertices[ 2 ].position.z - z0 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 5;
|
||||||
|
}
|
||||||
|
// CA na południu
|
||||||
|
mul = ( Shape.m_data.vertices[ 2 ].position.z - z0 ) * ( Shape.m_data.vertices[ 0 ].position.z - z0 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 6;
|
||||||
|
}
|
||||||
|
// AB na północy
|
||||||
|
mul = ( Shape.m_data.vertices[ 0 ].position.z - z1 ) * ( Shape.m_data.vertices[ 1 ].position.z - z1 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 12;
|
||||||
|
}
|
||||||
|
// BC na północy
|
||||||
|
mul = ( Shape.m_data.vertices[ 1 ].position.z - z1 ) * ( Shape.m_data.vertices[ 2 ].position.z - z1 );
|
||||||
|
if( mul < min ) {
|
||||||
|
min = mul;
|
||||||
|
divide = 13;
|
||||||
|
}
|
||||||
|
// CA na północy
|
||||||
|
mul = (Shape.m_data.vertices[2].position.z - z1) * (Shape.m_data.vertices[0].position.z - z1);
|
||||||
|
if( mul < min ) {
|
||||||
|
divide = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tworzymy jeden dodatkowy trójkąt, dzieląc jeden bok na przecięciu siatki kilometrowej
|
||||||
|
Shapes.emplace_back( Shape ); // copy current shape
|
||||||
|
auto &newshape = Shapes.back();
|
||||||
|
|
||||||
|
switch (divide & 3) {
|
||||||
|
// podzielenie jednego z boków, powstaje wierzchołek D
|
||||||
|
case 0: {
|
||||||
|
// podział AB (0-1) -> ADC i DBC
|
||||||
|
newshape.m_data.vertices[ 2 ] = Shape.m_data.vertices[ 2 ]; // wierzchołek C jest wspólny
|
||||||
|
newshape.m_data.vertices[ 1 ] = Shape.m_data.vertices[ 1 ]; // wierzchołek B przechodzi do nowego
|
||||||
|
if( divide & 4 ) {
|
||||||
|
Shape.m_data.vertices[ 1 ].set_from_z(
|
||||||
|
Shape.m_data.vertices[ 0 ],
|
||||||
|
Shape.m_data.vertices[ 1 ],
|
||||||
|
( ( divide & 8 ) ?
|
||||||
|
z1 :
|
||||||
|
z0 ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Shape.m_data.vertices[ 1 ].set_from_x(
|
||||||
|
Shape.m_data.vertices[ 0 ],
|
||||||
|
Shape.m_data.vertices[ 1 ],
|
||||||
|
( ( divide & 8 ) ?
|
||||||
|
x1 :
|
||||||
|
x0 ) );
|
||||||
|
}
|
||||||
|
newshape.m_data.vertices[ 0 ] = Shape.m_data.vertices[ 1 ]; // wierzchołek D jest wspólny
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
// podział BC (1-2) -> ABD i ADC
|
||||||
|
newshape.m_data.vertices[ 0 ] = Shape.m_data.vertices[ 0 ]; // wierzchołek A jest wspólny
|
||||||
|
newshape.m_data.vertices[ 2 ] = Shape.m_data.vertices[ 2 ]; // wierzchołek C przechodzi do nowego
|
||||||
|
if( divide & 4 ) {
|
||||||
|
Shape.m_data.vertices[ 2 ].set_from_z(
|
||||||
|
Shape.m_data.vertices[ 1 ],
|
||||||
|
Shape.m_data.vertices[ 2 ],
|
||||||
|
( ( divide & 8 ) ?
|
||||||
|
z1 :
|
||||||
|
z0 ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Shape.m_data.vertices[ 2 ].set_from_x(
|
||||||
|
Shape.m_data.vertices[ 1 ],
|
||||||
|
Shape.m_data.vertices[ 2 ],
|
||||||
|
( ( divide & 8 ) ?
|
||||||
|
x1 :
|
||||||
|
x0 ) );
|
||||||
|
}
|
||||||
|
newshape.m_data.vertices[ 1 ] = Shape.m_data.vertices[ 2 ]; // wierzchołek D jest wspólny
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
// podział CA (2-0) -> ABD i DBC
|
||||||
|
newshape.m_data.vertices[ 1 ] = Shape.m_data.vertices[ 1 ]; // wierzchołek B jest wspólny
|
||||||
|
newshape.m_data.vertices[ 2 ] = Shape.m_data.vertices[ 2 ]; // wierzchołek C przechodzi do nowego
|
||||||
|
if( divide & 4 ) {
|
||||||
|
Shape.m_data.vertices[ 2 ].set_from_z(
|
||||||
|
Shape.m_data.vertices[ 2 ],
|
||||||
|
Shape.m_data.vertices[ 0 ],
|
||||||
|
( ( divide & 8 ) ?
|
||||||
|
z1 :
|
||||||
|
z0 ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Shape.m_data.vertices[ 2 ].set_from_x(
|
||||||
|
Shape.m_data.vertices[ 2 ],
|
||||||
|
Shape.m_data.vertices[ 0 ],
|
||||||
|
( ( divide & 8 ) ?
|
||||||
|
x1 :
|
||||||
|
x0 ) );
|
||||||
|
}
|
||||||
|
newshape.m_data.vertices[ 0 ] = Shape.m_data.vertices[ 2 ]; // wierzchołek D jest wspólny
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// przeliczenie środków ciężkości obu
|
||||||
|
Shape.m_data.area.center = ( Shape.m_data.vertices[ 0 ].position + Shape.m_data.vertices[ 1 ].position + Shape.m_data.vertices[ 2 ].position ) / 3.0;
|
||||||
|
newshape.m_data.area.center = ( newshape.m_data.vertices[ 0 ].position + newshape.m_data.vertices[ 1 ].position + newshape.m_data.vertices[ 2 ].position ) / 3.0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// provides access to section enclosing specified point
|
||||||
|
basic_section &
|
||||||
|
basic_region::section( glm::dvec3 const &Location ) {
|
||||||
|
|
||||||
|
auto const column = static_cast<int>( std::floor( Location.x / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||||
|
auto const row = static_cast<int>( std::floor( Location.z / EU07_SECTIONSIZE + EU07_REGIONSIDESECTIONCOUNT / 2 ) );
|
||||||
|
|
||||||
|
return
|
||||||
|
m_sections[
|
||||||
|
clamp( row, 0, EU07_REGIONSIDESECTIONCOUNT - 1 ) * EU07_REGIONSIDESECTIONCOUNT
|
||||||
|
+ clamp( column, 0, EU07_REGIONSIDESECTIONCOUNT - 1 ) ] ;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // scene
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
172
scene.h
Normal file
172
scene.h
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
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 "parser.h"
|
||||||
|
#include "openglgeometrybank.h"
|
||||||
|
#include "scenenode.h"
|
||||||
|
#include "track.h"
|
||||||
|
#include "traction.h"
|
||||||
|
|
||||||
|
namespace scene {
|
||||||
|
|
||||||
|
int const EU07_CELLSIZE = 250;
|
||||||
|
int const EU07_SECTIONSIZE = 1000;
|
||||||
|
int const EU07_REGIONSIDESECTIONCOUNT = 500; // number of 1km sections along a side of square region
|
||||||
|
|
||||||
|
struct scratch_data {
|
||||||
|
|
||||||
|
std::stack<glm::dvec3> location_offset;
|
||||||
|
glm::vec3 location_rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// adds provided shape to the cell
|
||||||
|
void
|
||||||
|
insert( shape_node Shape );
|
||||||
|
// 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 );
|
||||||
|
// generates renderable version of held non-instanced geometry in specified geometry bank
|
||||||
|
void
|
||||||
|
create_geometry( geometrybank_handle const &Bank );
|
||||||
|
// sets center point of the cell
|
||||||
|
void
|
||||||
|
center( glm::dvec3 Center );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// types
|
||||||
|
using shapenode_sequence = std::vector<shape_node>;
|
||||||
|
using path_sequence = std::vector<TTrack *>;
|
||||||
|
using traction_sequence = std::vector<TTraction *>;
|
||||||
|
using instance_sequence = std::vector<TAnimModel *>;
|
||||||
|
// members
|
||||||
|
scene::bounding_area m_area { glm::dvec3(), static_cast<float>( 0.5 * M_SQRT2 * EU07_CELLSIZE + 0.25 * EU07_CELLSIZE ) };
|
||||||
|
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
|
||||||
|
path_sequence m_paths; // path pieces
|
||||||
|
instance_sequence m_instancesopaque;
|
||||||
|
instance_sequence m_instancetranslucent;
|
||||||
|
traction_sequence m_traction;
|
||||||
|
};
|
||||||
|
|
||||||
|
// basic scene partitioning structure, holds terrain geometry and collection of cells
|
||||||
|
class basic_section {
|
||||||
|
|
||||||
|
friend class opengl_renderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// methods
|
||||||
|
// adds provided shape to the section
|
||||||
|
void
|
||||||
|
insert( shape_node Shape );
|
||||||
|
// adds provided path to the section
|
||||||
|
void
|
||||||
|
insert( TTrack *Path );
|
||||||
|
// adds provided path to the section
|
||||||
|
void
|
||||||
|
insert( TTraction *Traction );
|
||||||
|
// adds provided model instance to the section
|
||||||
|
void
|
||||||
|
insert( TAnimModel *Instance );
|
||||||
|
// generates renderable version of held non-instanced geometry
|
||||||
|
void
|
||||||
|
create_geometry();
|
||||||
|
// sets center point of the section
|
||||||
|
void
|
||||||
|
center( glm::dvec3 Center );
|
||||||
|
|
||||||
|
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 + 0.25 * EU07_SECTIONSIZE ) };
|
||||||
|
bool m_active { false }; // whether the section holds any actual data, itself or in the cells
|
||||||
|
// 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();
|
||||||
|
// methods
|
||||||
|
// inserts provided shape in the region
|
||||||
|
void
|
||||||
|
insert_shape( shape_node Shape, scratch_data &Scratchpad );
|
||||||
|
// inserts provided track in the region
|
||||||
|
void
|
||||||
|
insert_path( TTrack *Path, 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 );
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// types
|
||||||
|
using section_array = std::array<basic_section, EU07_REGIONSIDESECTIONCOUNT * EU07_REGIONSIDESECTIONCOUNT>;
|
||||||
|
|
||||||
|
// methods
|
||||||
|
// checks whether specified point is within boundaries of the region
|
||||||
|
bool
|
||||||
|
point_inside( glm::dvec3 const &Location );
|
||||||
|
// trims provided shape to fit into a section, adds trimmed part at the end of provided list
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // scene
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
296
scenenode.cpp
Normal file
296
scenenode.cpp
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
/*
|
||||||
|
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, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // editor
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
253
scenenode.h
Normal file
253
scenenode.h
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
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"
|
||||||
|
|
||||||
|
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 { 0.0 };
|
||||||
|
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
|
||||||
|
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, node_data const &Nodedata );
|
||||||
|
// adds content of provided node to already enclosed geometry. returns: true if merge could be performed
|
||||||
|
bool
|
||||||
|
merge( shape_node &Shape );
|
||||||
|
// 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 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; }
|
||||||
|
glm::dvec3 const &
|
||||||
|
location() {
|
||||||
|
return m_location; };
|
||||||
|
void
|
||||||
|
location( glm::dvec3 const Location ) {
|
||||||
|
m_location = Location; }
|
||||||
|
bool
|
||||||
|
visible() const {
|
||||||
|
return m_visible; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// members
|
||||||
|
glm::dvec3 m_location;
|
||||||
|
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
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
521
simulation.cpp
Normal file
521
simulation.cpp
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
/*
|
||||||
|
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"
|
||||||
|
|
||||||
|
namespace simulation {
|
||||||
|
|
||||||
|
state_manager State;
|
||||||
|
event_manager Events;
|
||||||
|
memory_manager Memory;
|
||||||
|
path_table Paths;
|
||||||
|
traction_table Traction;
|
||||||
|
instance_manager Instances;
|
||||||
|
light_array Lights;
|
||||||
|
scene::basic_region Region;
|
||||||
|
|
||||||
|
bool
|
||||||
|
state_manager::deserialize( std::string const &Scenariofile ) {
|
||||||
|
|
||||||
|
// TODO: check first for presence of serialized binary files
|
||||||
|
// if this fails, fall back on the legacy text format
|
||||||
|
cParser scenarioparser( Scenariofile, cParser::buffer_FILE, Global::asCurrentSceneryPath, Global::bLoadTraction );
|
||||||
|
|
||||||
|
if( false == scenarioparser.ok() ) { return false; }
|
||||||
|
|
||||||
|
deserialize( scenarioparser );
|
||||||
|
// TODO: initialize links between loaded nodes
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restores class data from provided stream
|
||||||
|
void
|
||||||
|
state_manager::deserialize( cParser &Input ) {
|
||||||
|
|
||||||
|
scene::scratch_data importscratchpad;
|
||||||
|
// 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 },
|
||||||
|
{ "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( importscratchpad ) ) );
|
||||||
|
}
|
||||||
|
// deserialize content from the provided input
|
||||||
|
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 ) + ")" );
|
||||||
|
}
|
||||||
|
|
||||||
|
token = Input.getToken<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_firstinit( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
simulation::Paths.InitTracks();
|
||||||
|
simulation::Traction.InitTraction();
|
||||||
|
simulation::Events.InitEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
|
||||||
|
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" ) {
|
||||||
|
// TODO: implement
|
||||||
|
skip_until( Input, "enddynamic" );
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "track" ) {
|
||||||
|
|
||||||
|
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||||
|
|
||||||
|
auto *path { deserialize_path( Input, Scratchpad, nodedata ) };
|
||||||
|
// duplicates of named tracks are currently experimentally allowed
|
||||||
|
if( simulation::Paths.insert( path ) ) {
|
||||||
|
simulation::Region.insert_path( path, Scratchpad );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad scenario: track with duplicate name, \"" + path->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
/*
|
||||||
|
delete path;
|
||||||
|
delete pathnode;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "traction" ) {
|
||||||
|
|
||||||
|
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||||
|
|
||||||
|
auto *traction { deserialize_traction( Input, Scratchpad, nodedata ) };
|
||||||
|
// duplicates of named tracks are currently discarded
|
||||||
|
if( simulation::Traction.insert( traction ) ) {
|
||||||
|
simulation::Region.insert_traction( traction, Scratchpad );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad scenario: traction piece with duplicate name, \"" + traction->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "tractionpowersource" ) {
|
||||||
|
// TODO: implement
|
||||||
|
skip_until( Input, "end" );
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "model" ) {
|
||||||
|
|
||||||
|
if( nodedata.range_min < 0.0 ) {
|
||||||
|
// convert and import 3d terrain
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// regular instance of 3d mesh
|
||||||
|
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||||
|
|
||||||
|
auto *instance { deserialize_model( Input, Scratchpad, nodedata ) };
|
||||||
|
// model import can potentially fail
|
||||||
|
if( instance == nullptr ) { return; }
|
||||||
|
|
||||||
|
if( simulation::Instances.insert( instance ) ) {
|
||||||
|
simulation::Region.insert_instance( instance, Scratchpad );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad scenario: 3d model instance with duplicate name, \"" + instance->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( ( nodedata.type == "triangles" )
|
||||||
|
|| ( nodedata.type == "triangle_strip" )
|
||||||
|
|| ( nodedata.type == "triangle_fan" ) ) {
|
||||||
|
|
||||||
|
simulation::Region.insert_shape( scene::shape_node().deserialize( Input, nodedata ), Scratchpad );
|
||||||
|
}
|
||||||
|
else if( ( nodedata.type == "lines" )
|
||||||
|
|| ( nodedata.type == "line_strip" )
|
||||||
|
|| ( nodedata.type == "line_loop" ) ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
skip_until( Input, "endline" );
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "memcell" ) {
|
||||||
|
|
||||||
|
auto const inputline = Input.Line(); // cache in case we need to report error
|
||||||
|
|
||||||
|
auto *memorycell { deserialize_memorycell( Input, Scratchpad, nodedata ) };
|
||||||
|
// duplicates of named tracks are currently discarded
|
||||||
|
if( simulation::Memory.insert( memorycell ) ) {
|
||||||
|
/*
|
||||||
|
// TODO: implement this
|
||||||
|
simulation::Region.insert_memorycell( memorycell, Scratchpad );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ErrorLog( "Bad scenario: memory cell with duplicate name, \"" + memorycell->name() + "\" encountered in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
|
||||||
|
/*
|
||||||
|
delete memorycell;
|
||||||
|
delete memorycellnode;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "eventlauncher" ) {
|
||||||
|
// TODO: implement
|
||||||
|
skip_until( Input, "end" );
|
||||||
|
}
|
||||||
|
else if( nodedata.type == "sound" ) {
|
||||||
|
// TODO: implement
|
||||||
|
skip_until( Input, "endsound" );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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 " + 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 ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
skip_until( Input, "endtrainset" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
state_manager::deserialize_endtrainset( cParser &Input, scene::scratch_data &Scratchpad ) {
|
||||||
|
|
||||||
|
// TODO: implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 ) {
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
// adjust location
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
73
simulation.h
Normal file
73
simulation.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
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 "event.h"
|
||||||
|
#include "memcell.h"
|
||||||
|
#include "track.h"
|
||||||
|
#include "traction.h"
|
||||||
|
#include "animmodel.h"
|
||||||
|
#include "scene.h"
|
||||||
|
#include "lightarray.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
namespace simulation {
|
||||||
|
|
||||||
|
class state_manager {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// types
|
||||||
|
|
||||||
|
// methods
|
||||||
|
bool
|
||||||
|
deserialize( std::string const &Scenariofile );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// methods
|
||||||
|
// restores class data from provided stream
|
||||||
|
void deserialize( cParser &Input );
|
||||||
|
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_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 );
|
||||||
|
TMemCell * deserialize_memorycell( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||||
|
TAnimModel * deserialize_model( cParser &Input, scene::scratch_data &Scratchpad, scene::node_data const &Nodedata );
|
||||||
|
// 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_manager Memory;
|
||||||
|
extern path_table Paths;
|
||||||
|
extern traction_table Traction;
|
||||||
|
extern instance_manager Instances;
|
||||||
|
extern light_array Lights;
|
||||||
|
extern scene::basic_region Region;
|
||||||
|
|
||||||
|
} // simulation
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
3
stdafx.h
3
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>
|
||||||
@@ -93,3 +94,5 @@
|
|||||||
#include <glm/gtx/norm.hpp>
|
#include <glm/gtx/norm.hpp>
|
||||||
|
|
||||||
#include "openglmatrixstack.h"
|
#include "openglmatrixstack.h"
|
||||||
|
|
||||||
|
//#define EU07_USE_OLD_GROUNDCODE
|
||||||
|
|||||||
35
vertex.cpp
Normal file
35
vertex.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
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 "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 );
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
Reference in New Issue
Block a user