16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 20:59:19 +02:00

Merge remote-tracking branch 'tmj-fstate/mover_in_c++' into mover_in_c++

This commit is contained in:
firleju
2017-08-07 05:59:33 +02:00
49 changed files with 1153 additions and 1063 deletions

View File

@@ -472,8 +472,10 @@ bool TAnimModel::Load(cParser *parser, bool ter)
if( name.substr( name.rfind( '.' ) ) == ".t3d" ) { if( name.substr( name.rfind( '.' ) ) == ".t3d" ) {
name[ name.length() - 3 ] = 'e'; name[ name.length() - 3 ] = 'e';
} }
#ifdef EU07_USE_OLD_TERRAINCODE
Global::asTerrainModel = name; Global::asTerrainModel = name;
WriteLog("Terrain model \"" + name + "\" will be created."); WriteLog("Terrain model \"" + name + "\" will be created.");
#endif
} }
else else
ErrorLog("Missed file: " + name); ErrorLog("Missed file: " + name);
@@ -632,13 +634,7 @@ TSubModel * TAnimModel::TerrainSquare(int n)
{ // pobieranie wskaźników do pierwszego submodelu { // pobieranie wskaźników do pierwszego submodelu
return pModel ? pModel->TerrainSquare(n) : 0; return pModel ? pModel->TerrainSquare(n) : 0;
}; };
#ifdef EU07_USE_OLD_RENDERCODE
void TAnimModel::TerrainRenderVBO(int n)
{ // renderowanie terenu z VBO
if (pModel)
pModel->TerrainRenderVBO(n);
};
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TAnimModel::Advanced() void TAnimModel::Advanced()

View File

@@ -144,7 +144,7 @@ class TAnimModel {
material_data m_materialdata; material_data m_materialdata;
std::string asText; // tekst dla wyświetlacza znakowego std::string asText; // tekst dla wyświetlacza znakowego
TAnimAdvanced *pAdvanced; TAnimAdvanced *pAdvanced { nullptr };
void Advanced(); void Advanced();
TLightState lsLights[iMaxNumLights]; TLightState lsLights[iMaxNumLights];
float fDark; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?) float fDark; // poziom zapalanie światła (powinno być chyba powiązane z danym światłem?)

View File

@@ -352,7 +352,8 @@ void TCamera::Update()
} }
*/ */
if( ( Type == tp_Free ) if( ( Type == tp_Free )
|| ( false == Global::ctrlState ) ) { || ( false == Global::ctrlState )
|| ( true == DebugCameraFlag) ) {
// ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed // ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed
if( m_keys.up ) if( m_keys.up )
Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -m_moverate.y, m_moverate.y ); Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -m_moverate.y, m_moverate.y );
@@ -371,7 +372,8 @@ void TCamera::Update()
} }
#endif #endif
if( Type == tp_Free ) { if( ( Type == tp_Free )
|| ( true == DebugCameraFlag ) ) {
// free movement position update is handled here, movement while in vehicle is handled by train update // free movement position update is handled here, movement while in vehicle is handled by train update
vector3 Vec = Velocity; vector3 Vec = Velocity;
Vec.RotateY( Yaw ); Vec.RotateY( Yaw );
@@ -379,35 +381,9 @@ void TCamera::Update()
} }
} }
vector3 TCamera::GetDirection() vector3 TCamera::GetDirection() {
{
matrix4x4 mat;
vector3 Vec;
Vec = vector3(0, 0, 1);
Vec.RotateY(Yaw);
return (Normalize(Vec)); return glm::normalize( glm::rotateY<float>( glm::vec3{ 0.f, 0.f, 1.f }, Yaw ) );
}
bool TCamera::SetMatrix()
{
glRotated( -Roll * 180.0 / M_PI, 0.0, 0.0, 1.0 ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
glRotated( -Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0 );
glRotated( -Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // w zewnętrznym widoku: kierunek patrzenia
if( Type == tp_Follow )
{
gluLookAt(
Pos.x, Pos.y, Pos.z,
LookAt.x, LookAt.y, LookAt.z,
vUp.x, vUp.y, vUp.z); // Ra: pOffset is zero
}
else {
glTranslated( -Pos.x, -Pos.y, -Pos.z ); // nie zmienia kierunku patrzenia
}
Global::SetCameraPosition(Pos); // było +pOffset
return true;
} }
bool TCamera::SetMatrix( glm::dmat4 &Matrix ) { bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
@@ -416,7 +392,7 @@ bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) ); Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) );
Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia
if( Type == tp_Follow ) { if( ( Type == tp_Follow ) && ( false == DebugCameraFlag ) ) {
Matrix *= glm::lookAt( Matrix *= glm::lookAt(
glm::dvec3{ Pos }, glm::dvec3{ Pos },
@@ -427,7 +403,6 @@ bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
Matrix = glm::translate( Matrix, glm::dvec3{ -Pos } ); // nie zmienia kierunku patrzenia Matrix = glm::translate( Matrix, glm::dvec3{ -Pos } ); // nie zmienia kierunku patrzenia
} }
Global::SetCameraPosition( Pos ); // było +pOffset
return true; return true;
} }
@@ -446,4 +421,3 @@ void TCamera::Stop()
Type = tp_Follow; Type = tp_Follow;
Velocity = vector3(0, 0, 0); Velocity = vector3(0, 0, 0);
}; };

View File

@@ -57,7 +57,6 @@ class TCamera
void OnCommand( command_data const &Command ); void OnCommand( command_data const &Command );
void Update(); void Update();
vector3 GetDirection(); vector3 GetDirection();
bool SetMatrix();
bool SetMatrix(glm::dmat4 &Matrix); bool SetMatrix(glm::dmat4 &Matrix);
void RaLook(); void RaLook();
void Stop(); void Stop();

View File

@@ -1335,7 +1335,7 @@ void TController::TablePurger()
for( std::size_t idx = 0; idx < sSpeedTable.size() - 1; ++idx ) { for( std::size_t idx = 0; idx < sSpeedTable.size() - 1; ++idx ) {
auto const &speedpoint = sSpeedTable[ idx ]; auto const &speedpoint = sSpeedTable[ idx ];
if( ( 0 == ( speedpoint.iFlags & spEnabled ) ) if( ( 0 == ( speedpoint.iFlags & spEnabled ) )
|| ( ( speedpoint.iFlags & ( spElapsed | spTrack | spCurve | spSwitch ) == ( spElapsed | spTrack | spCurve ) ) || ( ( ( speedpoint.iFlags & ( spElapsed | spTrack | spCurve | spSwitch ) ) == ( spElapsed | spTrack | spCurve ) )
&& ( speedpoint.fVelNext < 0.0 ) ) ) { && ( speedpoint.fVelNext < 0.0 ) ) ) {
// NOTE: we could break out early here, but running through entire thing gives us exact size needed for new table // NOTE: we could break out early here, but running through entire thing gives us exact size needed for new table
++trimcount; ++trimcount;
@@ -1357,7 +1357,7 @@ void TController::TablePurger()
} }
auto const &speedpoint = sSpeedTable[ idx ]; auto const &speedpoint = sSpeedTable[ idx ];
if( ( 0 == ( speedpoint.iFlags & spEnabled ) ) if( ( 0 == ( speedpoint.iFlags & spEnabled ) )
|| ( ( speedpoint.iFlags & ( spElapsed | spTrack | spCurve | spSwitch ) == ( spElapsed | spTrack | spCurve ) ) || ( ( ( speedpoint.iFlags & ( spElapsed | spTrack | spCurve | spSwitch ) ) == ( spElapsed | spTrack | spCurve ) )
&& ( speedpoint.fVelNext < 0.0 ) ) ) { && ( speedpoint.fVelNext < 0.0 ) ) ) {
// if the trimmed point happens to be currently active semaphor we need to invalidate their placements // if the trimmed point happens to be currently active semaphor we need to invalidate their placements
if( idx == SemNextIndex ) { if( idx == SemNextIndex ) {

View File

@@ -185,9 +185,10 @@ float TDynamicObject::GetEPP()
// od strony sprzegu (coupler_nr) obiektu (start) // od strony sprzegu (coupler_nr) obiektu (start)
TDynamicObject *temp = this; TDynamicObject *temp = this;
int coupler_nr = 0; int coupler_nr = 0;
float eq = 0, am = 0; double eq = 0.0;
double am = 0.0;
for (int i = 0; i < 300; i++) // ograniczenie do 300 na wypadek zapętlenia składu for (int i = 0; i < 300; ++i) // ograniczenie do 300 na wypadek zapętlenia składu
{ {
if (!temp) if (!temp)
break; // Ra: zabezpieczenie przed ewentaulnymi błędami sprzęgów break; // Ra: zabezpieczenie przed ewentaulnymi błędami sprzęgów
@@ -2732,26 +2733,20 @@ bool TDynamicObject::Update(double dt, double dt1)
if (Mechanik) if (Mechanik)
{ // Ra 2F3F: do Driver.cpp to przenieść? { // Ra 2F3F: do Driver.cpp to przenieść?
MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG
if ((Mechanik->Primary()) && if( ( Mechanik->Primary() )
(MoverParameters->EngineType == ElectricInductionMotor)) // jesli glowny i z && ( MoverParameters->EngineType == ElectricInductionMotor ) ) {
// asynchronami, to // jesli glowny i z asynchronami, to niech steruje hamulcem lacznie dla calego pociagu/ezt
// niech steruje auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0);
{ // hamulcem lacznie dla calego pociagu/ezt auto FED { 0.0 };
bool kier = (DirectionGet() * MoverParameters->ActiveCab > 0); auto np { 0 };
float FED = 0; auto masa { 0.0 };
int np = 0; auto FrED { 0.0 };
float masa = 0; auto masamax { 0.0 };
float FrED = 0; auto FmaxPN { 0.0 };
float masamax = 0; auto FfulED { 0.0 };
float FmaxPN = 0; auto FmaxED { 0.0 };
float FfulED = 0; auto Frj { 0.0 };
float FmaxED = 0; auto osie { 0 };
float Fzad = 0;
float FzadED = 0;
float FzadPN = 0;
float Frj = 0;
float amax = 0;
float osie = 0;
// 1. ustal wymagana sile hamowania calego pociagu // 1. ustal wymagana sile hamowania calego pociagu
// - opoznienie moze byc ustalane na podstawie charakterystyki // - opoznienie moze byc ustalane na podstawie charakterystyki
// - opoznienie moze byc ustalane na podstawie mas i cisnien granicznych // - opoznienie moze byc ustalane na podstawie mas i cisnien granicznych
@@ -2762,11 +2757,14 @@ bool TDynamicObject::Update(double dt, double dt1)
for (TDynamicObject *p = GetFirstDynamic(MoverParameters->ActiveCab < 0 ? 1 : 0, 4); p; for (TDynamicObject *p = GetFirstDynamic(MoverParameters->ActiveCab < 0 ? 1 : 0, 4); p;
(kier ? p = p->NextC(4) : p = p->PrevC(4))) (kier ? p = p->NextC(4) : p = p->PrevC(4)))
{ {
np++; ++np;
masamax += p->MoverParameters->MBPM + masamax +=
(p->MoverParameters->MBPM > 1 ? 0 : p->MoverParameters->Mass) + p->MoverParameters->MBPM
p->MoverParameters->Mred; + ( p->MoverParameters->MBPM > 1.0 ?
float Nmax = ((p->MoverParameters->P2FTrans * p->MoverParameters->MaxBrakePress[0] - 0.0 :
p->MoverParameters->Mass )
+ p->MoverParameters->Mred;
auto const Nmax = ((p->MoverParameters->P2FTrans * p->MoverParameters->MaxBrakePress[0] -
p->MoverParameters->BrakeCylSpring) * p->MoverParameters->BrakeCylSpring) *
p->MoverParameters->BrakeCylMult[0] - p->MoverParameters->BrakeCylMult[0] -
p->MoverParameters->BrakeSlckAdj) * p->MoverParameters->BrakeSlckAdj) *
@@ -2780,18 +2778,19 @@ bool TDynamicObject::Update(double dt, double dt1)
0) ? 0) ?
p->MoverParameters->eimc[eimc_p_Fh] * 1000 : p->MoverParameters->eimc[eimc_p_Fh] * 1000 :
0); // chwilowy max ED -> do rozdzialu sil 0); // chwilowy max ED -> do rozdzialu sil
FED -= Min0R(p->MoverParameters->eimv[eimv_Fmax], 0) * FED -= std::min(p->MoverParameters->eimv[eimv_Fmax], 0.0) *
1000; // chwilowy max ED -> do rozdzialu sil 1000; // chwilowy max ED -> do rozdzialu sil
FfulED = Min0R(p->MoverParameters->eimv[eimv_Fful], 0) * FfulED = std::min(p->MoverParameters->eimv[eimv_Fful], 0.0) *
1000; // chwilowy max ED -> do rozdzialu sil 1000; // chwilowy max ED -> do rozdzialu sil
FrED -= Min0R(p->MoverParameters->eimv[eimv_Fr], 0) * FrED -= std::min(p->MoverParameters->eimv[eimv_Fr], 0.0) *
1000; // chwilowo realizowane ED -> do pneumatyki 1000; // chwilowo realizowane ED -> do pneumatyki
Frj += Max0R(p->MoverParameters->eimv[eimv_Fr], 0) * Frj += std::max(p->MoverParameters->eimv[eimv_Fr], 0.0) *
1000;// chwilowo realizowany napęd -> do utrzymującego 1000;// chwilowo realizowany napęd -> do utrzymującego
masa += p->MoverParameters->TotalMass; masa += p->MoverParameters->TotalMass;
osie += p->MoverParameters->NAxles; osie += p->MoverParameters->NAxles;
} }
amax = FmaxPN / masamax;
auto const amax = FmaxPN / masamax;
if ((MoverParameters->Vel < 0.5) && (MoverParameters->BrakePress > 0.2) || if ((MoverParameters->Vel < 0.5) && (MoverParameters->BrakePress > 0.2) ||
(dDoorMoveL > 0.001) || (dDoorMoveR > 0.001)) (dDoorMoveL > 0.001) || (dDoorMoveR > 0.001))
{ {
@@ -2808,24 +2807,28 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->ShuntModeAllow = (MoverParameters->BrakePress > 0.2) && MoverParameters->ShuntModeAllow = (MoverParameters->BrakePress > 0.2) &&
(MoverParameters->LocalBrakeRatio() < 0.01); (MoverParameters->LocalBrakeRatio() < 0.01);
} }
Fzad = amax * MoverParameters->LocalBrakeRatio() * masa; auto Fzad = amax * MoverParameters->LocalBrakeRatio() * masa;
if ((MoverParameters->ScndS) && if ((MoverParameters->ScndS) &&
(MoverParameters->Vel > MoverParameters->eimc[eimc_p_Vh1]) && (FmaxED > 0)) (MoverParameters->Vel > MoverParameters->eimc[eimc_p_Vh1]) && (FmaxED > 0))
{ {
Fzad = Min0R(MoverParameters->LocalBrakeRatio() * FmaxED, FfulED); Fzad = std::min(MoverParameters->LocalBrakeRatio() * FmaxED, FfulED);
} }
if (((MoverParameters->ShuntMode) && (Frj < 0.0015 * masa)) || if (((MoverParameters->ShuntMode) && (Frj < 0.0015 * masa)) ||
(MoverParameters->V * MoverParameters->DirAbsolute < -0.2)) (MoverParameters->V * MoverParameters->DirAbsolute < -0.2))
{ {
Fzad = Max0R(MoverParameters->StopBrakeDecc * masa, Fzad); Fzad = std::max(MoverParameters->StopBrakeDecc * masa, Fzad);
} }
if (MoverParameters->BrakeHandle == MHZ_EN57?MoverParameters->BrakeOpModeFlag & bom_MED:MoverParameters->EpFuse) auto FzadED { 0.0 };
FzadED = Min0R(Fzad, FmaxED); if( ( MoverParameters->EpFuse )
else || ( ( MoverParameters->BrakeHandle == MHZ_EN57 )
FzadED = 0; && ( MoverParameters->BrakeOpModeFlag & bom_MED ) ) ) {
FzadPN = Fzad - FrED; FzadED = std::min( Fzad, FmaxED );
}
auto const FzadPN = Fzad - FrED;
//np = 0; //np = 0;
// BUG: likely memory leak, allocation per inner loop, deleted only once outside
// TODO: sort this shit out
bool* PrzekrF = new bool[np]; bool* PrzekrF = new bool[np];
float nPrzekrF = 0; float nPrzekrF = 0;
bool test = true; bool test = true;
@@ -2849,7 +2852,7 @@ bool TDynamicObject::Update(double dt, double dt1)
for (TDynamicObject *p = GetFirstDynamic(MoverParameters->ActiveCab < 0 ? 1 : 0, 4); p; for (TDynamicObject *p = GetFirstDynamic(MoverParameters->ActiveCab < 0 ? 1 : 0, 4); p;
p = (kier == true ? p->NextC(4) : p->PrevC(4)) ) p = (kier == true ? p->NextC(4) : p->PrevC(4)) )
{ {
float Nmax = ((p->MoverParameters->P2FTrans * p->MoverParameters->MaxBrakePress[0] - auto const Nmax = ((p->MoverParameters->P2FTrans * p->MoverParameters->MaxBrakePress[0] -
p->MoverParameters->BrakeCylSpring) * p->MoverParameters->BrakeCylSpring) *
p->MoverParameters->BrakeCylMult[0] - p->MoverParameters->BrakeCylMult[0] -
p->MoverParameters->BrakeSlckAdj) * p->MoverParameters->BrakeSlckAdj) *
@@ -2864,8 +2867,8 @@ bool TDynamicObject::Update(double dt, double dt1)
FzED[i] = (FmaxED > 0 ? FzadED / FmaxED : 0); FzED[i] = (FmaxED > 0 ? FzadED / FmaxED : 0);
p->MoverParameters->AnPos = p->MoverParameters->AnPos =
(MoverParameters->ScndS ? MoverParameters->LocalBrakeRatio() : FzED[i]); (MoverParameters->ScndS ? MoverParameters->LocalBrakeRatio() : FzED[i]);
FzEP[i] = FzadPN * p->MoverParameters->NAxles / osie; FzEP[ i ] = static_cast<float>( FzadPN * p->MoverParameters->NAxles ) / static_cast<float>( osie );
i++; ++i;
p->MoverParameters->ShuntMode = MoverParameters->ShuntMode; p->MoverParameters->ShuntMode = MoverParameters->ShuntMode;
p->MoverParameters->ShuntModeAllow = MoverParameters->ShuntModeAllow; p->MoverParameters->ShuntModeAllow = MoverParameters->ShuntModeAllow;
} }
@@ -2896,7 +2899,7 @@ bool TDynamicObject::Update(double dt, double dt1)
FzEP[i] = 0; FzEP[i] = 0;
przek += przek1; przek += przek1;
} }
i++; ++i;
} }
i = 0; i = 0;
przek = przek / (np - nPrzekrF); przek = przek / (np - nPrzekrF);
@@ -2907,7 +2910,7 @@ bool TDynamicObject::Update(double dt, double dt1)
{ {
FzEP[i] += przek; FzEP[i] += przek;
} }
i++; ++i;
} }
} }
i = 0; i = 0;
@@ -2938,31 +2941,8 @@ bool TDynamicObject::Update(double dt, double dt1)
p->MoverParameters->LocalBrakePosA = p->MoverParameters->LocalBrakePosA; p->MoverParameters->LocalBrakePosA = p->MoverParameters->LocalBrakePosA;
else else
p->MoverParameters->LocalBrakePosA = 0; p->MoverParameters->LocalBrakePosA = 0;
i++; ++i;
} }
/* ////ALGORYTM 1 - KAZDEMU PO ROWNO
for (TDynamicObject *p = GetFirstDynamic(MoverParameters->ActiveCab < 0 ? 1 : 0); p;
(iDirection > 0 ? p = p->NextC(4) : p = p->PrevC(4)))
{
float Nmax = ((p->MoverParameters->P2FTrans * p->MoverParameters->MaxBrakePress[0] -
p->MoverParameters->BrakeCylSpring) *
p->MoverParameters->BrakeCylMult[0] -
p->MoverParameters->BrakeSlckAdj) *
p->MoverParameters->BrakeCylNo * p->MoverParameters->BrakeRigEff;
float FmaxPoj = Nmax *
p->MoverParameters->Hamulec->GetFC(
Nmax / (p->MoverParameters->NAxles * p->MoverParameters->NBpA),
p->MoverParameters->Vel) *
1000; // sila hamowania pn
// Fpoj=(FED>0?-FzadED*p->MoverParameters->eimv[eimv_Fmax]*1000/FED:0);
// p->MoverParameters->AnPos=(p->MoverParameters->eimc[eimc_p_Fh]>1?0.001f*Fpoj/(p->MoverParameters->eimc[eimc_p_Fh]):0);
p->MoverParameters->AnPos = (FmaxED > 0 ? FzadED / FmaxED : 0);
// Fpoj = FzadPN * Min0R(p->MoverParameters->TotalMass / masa, 1);
// p->MoverParameters->LocalBrakePosA =
// (p->MoverParameters->SlippingWheels ? 0 : Min0R(Max0R(Fpoj / FmaxPoj, 0), 1));
p->MoverParameters->LocalBrakePosA = (p->MoverParameters->SlippingWheels ? 0 : FzadPN / FmaxPN);
} */
MED[0][0] = masa*0.001; MED[0][0] = masa*0.001;
MED[0][1] = amax; MED[0][1] = amax;
@@ -2979,14 +2959,6 @@ bool TDynamicObject::Update(double dt, double dt1)
delete[] FmaxEP; delete[] FmaxEP;
} }
// yB: cos (AI) tu jest nie kompatybilne z czyms (hamulce)
// if (Controller!=Humandriver)
// if (Mechanik->LastReactionTime>0.5)
// {
// MoverParameters->BrakeCtrlPos=0;
// Mechanik->LastReactionTime=0;
// }
Mechanik->UpdateSituation(dt1); // przebłyski świadomości AI Mechanik->UpdateSituation(dt1); // przebłyski świadomości AI
} }

View File

@@ -78,8 +78,8 @@ void screenshot_save_thread( char *img )
png_image png; png_image png;
memset(&png, 0, sizeof(png_image)); memset(&png, 0, sizeof(png_image));
png.version = PNG_IMAGE_VERSION; png.version = PNG_IMAGE_VERSION;
png.width = Global::ScreenWidth; png.width = Global::iWindowWidth;
png.height = Global::ScreenHeight; png.height = Global::iWindowHeight;
png.format = PNG_FORMAT_RGB; png.format = PNG_FORMAT_RGB;
char datetime[64]; char datetime[64];
@@ -95,7 +95,7 @@ void screenshot_save_thread( char *img )
std::string filename = "screenshots/" + std::string(datetime) + std::string filename = "screenshots/" + std::string(datetime) +
"_" + std::to_string(perf) + ".png"; "_" + std::to_string(perf) + ".png";
if (png_image_write_to_file(&png, filename.c_str(), 0, img, -Global::ScreenWidth * 3, nullptr) == 1) if (png_image_write_to_file(&png, filename.c_str(), 0, img, -Global::iWindowWidth * 3, nullptr) == 1)
WriteLog("saved " + filename + "."); WriteLog("saved " + filename + ".");
else else
WriteLog("failed to save screenshot."); WriteLog("failed to save screenshot.");
@@ -105,8 +105,8 @@ void screenshot_save_thread( char *img )
void make_screenshot() void make_screenshot()
{ {
char *img = new char[Global::ScreenWidth * Global::ScreenHeight * 3]; char *img = new char[Global::iWindowWidth * Global::iWindowHeight * 3];
glReadPixels(0, 0, Global::ScreenWidth, Global::ScreenHeight, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)img); glReadPixels(0, 0, Global::iWindowWidth, Global::iWindowHeight, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)img);
std::thread t(screenshot_save_thread, img); std::thread t(screenshot_save_thread, img);
t.detach(); t.detach();
@@ -117,8 +117,8 @@ void window_resize_callback(GLFWwindow *window, int w, int h)
{ {
// NOTE: we have two variables which basically do the same thing as we don't have dynamic fullscreen toggle // NOTE: we have two variables which basically do the same thing as we don't have dynamic fullscreen toggle
// TBD, TODO: merge them? // TBD, TODO: merge them?
Global::ScreenWidth = Global::iWindowWidth = w; Global::iWindowWidth = w;
Global::ScreenHeight = Global::iWindowHeight = h; Global::iWindowHeight = h;
Global::fDistanceFactor = std::max( 0.5f, h / 768.0f ); // not sure if this is really something we want to use Global::fDistanceFactor = std::max( 0.5f, h / 768.0f ); // not sure if this is really something we want to use
glViewport(0, 0, w, h); glViewport(0, 0, w, h);
} }

View File

@@ -223,7 +223,7 @@ void TEvent::Load(cParser *parser, vector3 *org)
parser->getTokens(1, false); // case sensitive parser->getTokens(1, false); // case sensitive
*parser >> token; *parser >> token;
// str = AnsiString(token.c_str()); // str = AnsiString(token.c_str());
Params[0].asText = new char[token.length() + 1]; Params[0].asText = new char[token.length() + 1]; // BUG: source of memory leak
strcpy(Params[0].asText, token.c_str()); strcpy(Params[0].asText, token.c_str());
if (token != "*") // czy ma zostać bez zmian? if (token != "*") // czy ma zostać bez zmian?
iFlags |= update_memstring; iFlags |= update_memstring;

View File

@@ -241,7 +241,7 @@ public:
e[i + 2] = f; // zamiana Y i Z e[i + 2] = f; // zamiana Y i Z
} }
}; };
inline float4x4 &Rotation(double angle, float3 axis); inline float4x4 &Rotation(float const angle, float3 const &axis);
inline bool IdentityIs() inline bool IdentityIs()
{ // sprawdzenie jednostkowości { // sprawdzenie jednostkowości
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
@@ -270,34 +270,30 @@ inline glm::vec3 operator*( const float4x4 &m, const glm::vec3 &v ) { // mnożen
v.x * m[ 0 ][ 2 ] + v.y * m[ 1 ][ 2 ] + v.z * m[ 2 ][ 2 ] + m[ 3 ][ 2 ] ); v.x * m[ 0 ][ 2 ] + v.y * m[ 1 ][ 2 ] + v.z * m[ 2 ][ 2 ] + m[ 3 ][ 2 ] );
} }
inline float4x4 &float4x4::Rotation(double angle, float3 axis) inline float4x4 &float4x4::Rotation(float const Angle, float3 const &Axis)
{ {
double c = cos(angle); auto const c = std::cos(Angle);
double s = sin(angle); auto const s = std::sin(Angle);
// One minus c (short name for legibility of formulai) // One minus c (short name for legibility of formulai)
double omc = (1 - c); auto const omc = (1.f - c);
if (axis.Length() != 1.0f) auto const axis = SafeNormalize(Axis);
axis = SafeNormalize(axis); auto const xs = axis.x * s;
double x = axis.x; auto const ys = axis.y * s;
double y = axis.y; auto const zs = axis.z * s;
double z = axis.z; auto const xyomc = axis.x * axis.y * omc;
double xs = x * s; auto const xzomc = axis.x * axis.z * omc;
double ys = y * s; auto const yzomc = axis.y * axis.z * omc;
double zs = z * s; e[0] = axis.x * axis.x * omc + c;
double xyomc = x * y * omc;
double xzomc = x * z * omc;
double yzomc = y * z * omc;
e[0] = x * x * omc + c;
e[1] = xyomc + zs; e[1] = xyomc + zs;
e[2] = xzomc - ys; e[2] = xzomc - ys;
e[3] = 0; e[3] = 0;
e[4] = xyomc - zs; e[4] = xyomc - zs;
e[5] = y * y * omc + c; e[5] = axis.y * axis.y * omc + c;
e[6] = yzomc + xs; e[6] = yzomc + xs;
e[7] = 0; e[7] = 0;
e[8] = xzomc + ys; e[8] = xzomc + ys;
e[9] = yzomc - xs; e[9] = yzomc - xs;
e[10] = z * z * omc + c; e[10] = axis.z * axis.z * omc + c;
e[11] = 0; e[11] = 0;
e[12] = 0; e[12] = 0;
e[13] = 0; e[13] = 0;

View File

@@ -180,7 +180,7 @@ void TGauge::DecValue(double fNewDesired)
void void
TGauge::UpdateValue( double fNewDesired, PSound Fallbacksound ) { TGauge::UpdateValue( double fNewDesired, PSound Fallbacksound ) {
auto const desiredtimes100 = static_cast<int>( 100.0 * fNewDesired ); auto const desiredtimes100 = static_cast<int>( std::round( 100.0 * fNewDesired ) );
if( static_cast<int>( std::round( 100.0 * ( fDesiredValue - fOffset ) / fScale ) ) == desiredtimes100 ) { if( static_cast<int>( std::round( 100.0 * ( fDesiredValue - fOffset ) / fScale ) ) == desiredtimes100 ) {
return; return;
} }

View File

@@ -66,14 +66,12 @@ cParser *Global::pParser = NULL;
int Global::iSegmentsRendered = 90; // ilość segmentów do regulacji wydajności int Global::iSegmentsRendered = 90; // ilość segmentów do regulacji wydajności
TCamera *Global::pCamera = NULL; // parametry kamery TCamera *Global::pCamera = NULL; // parametry kamery
TDynamicObject *Global::pUserDynamic = NULL; // pojazd użytkownika, renderowany bez trzęsienia TDynamicObject *Global::pUserDynamic = NULL; // pojazd użytkownika, renderowany bez trzęsienia
/*
std::string Global::asTranscript[5]; // napisy na ekranie (widoczne)
*/
TTranscripts Global::tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie TTranscripts Global::tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie
float4 Global::UITextColor = float4( 225.0 / 255.0f, 225.0f / 255.0f, 225.0f / 255.0f, 1.0f ); float4 Global::UITextColor = float4( 225.0 / 255.0f, 225.0f / 255.0f, 225.0f / 255.0f, 1.0f );
// parametry scenerii // parametry scenerii
vector3 Global::pCameraPosition; vector3 Global::pCameraPosition;
vector3 Global::DebugCameraPosition;
double Global::pCameraRotation; double Global::pCameraRotation;
double Global::pCameraRotationDeg; double Global::pCameraRotationDeg;
std::vector<vector3> Global::FreeCameraInit; std::vector<vector3> Global::FreeCameraInit;
@@ -84,11 +82,12 @@ GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
double Global::fFogStart = 1700; double Global::fFogStart = 1700;
double Global::fFogEnd = 2000; double Global::fFogEnd = 2000;
float Global::Overcast { 0.1f }; // NOTE: all this weather stuff should be moved elsewhere float Global::Overcast { 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
float Global::BaseDrawRange { 2500.f };
opengl_light Global::DayLight; opengl_light Global::DayLight;
int Global::DynamicLightCount { 3 }; int Global::DynamicLightCount { 3 };
bool Global::ScaleSpecularValues { true }; bool Global::ScaleSpecularValues { true };
bool Global::RenderShadows { false }; bool Global::RenderShadows { false };
Global::shadowtune_t Global::shadowtune = { 2048, 200.0f, 150.0f, 100.0f }; Global::shadowtune_t Global::shadowtune = { 2048, 250.f, 250.f, 500.f };
bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki
bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach
int Global::iHiddenEvents = 1; // czy łączyć eventy z torami poprzez nazwę toru int Global::iHiddenEvents = 1; // czy łączyć eventy z torami poprzez nazwę toru
@@ -98,7 +97,7 @@ int Global::Keys[MaxKeys];
bool Global::RealisticControlMode{ false }; bool Global::RealisticControlMode{ false };
int Global::iWindowWidth = 800; int Global::iWindowWidth = 800;
int Global::iWindowHeight = 600; int Global::iWindowHeight = 600;
float Global::fDistanceFactor = Global::ScreenHeight / 768.0; // baza do przeliczania odległości dla LoD float Global::fDistanceFactor = Global::iWindowHeight / 768.0; // baza do przeliczania odległości dla LoD
int Global::iFeedbackMode = 1; // tryb pracy informacji zwrotnej int Global::iFeedbackMode = 1; // tryb pracy informacji zwrotnej
int Global::iFeedbackPort = 0; // dodatkowy adres dla informacji zwrotnych int Global::iFeedbackPort = 0; // dodatkowy adres dla informacji zwrotnych
bool Global::InputGamepad{ true }; bool Global::InputGamepad{ true };

View File

@@ -170,6 +170,7 @@ class Global
static int Keys[MaxKeys]; static int Keys[MaxKeys];
static bool RealisticControlMode; // controls ability to steer the vehicle from outside views static bool RealisticControlMode; // controls ability to steer the vehicle from outside views
static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie
static Math3D::vector3 DebugCameraPosition; // pozycja kamery w świecie
static double static double
pCameraRotation; // kierunek bezwzględny kamery w świecie: 0=północ, 90°=zachód (-azymut) pCameraRotation; // kierunek bezwzględny kamery w świecie: 0=północ, 90°=zachód (-azymut)
static double pCameraRotationDeg; // w stopniach, dla animacji billboard static double pCameraRotationDeg; // w stopniach, dla animacji billboard
@@ -223,6 +224,7 @@ class Global
// static bool bTimeChange; // static bool bTimeChange;
// TODO: put these things in the renderer // TODO: put these things in the renderer
static float BaseDrawRange;
static opengl_light DayLight; static opengl_light DayLight;
static int DynamicLightCount; static int DynamicLightCount;
static bool ScaleSpecularValues; static bool ScaleSpecularValues;
@@ -315,9 +317,6 @@ class Global
// informacje podczas kalibracji // informacje podczas kalibracji
static double fBrakeStep; // krok zmiany hamulca dla klawiszy [Num3] i [Num9] static double fBrakeStep; // krok zmiany hamulca dla klawiszy [Num3] i [Num9]
static bool bJoinEvents; // czy grupować eventy o tych samych nazwach static bool bJoinEvents; // czy grupować eventy o tych samych nazwach
/*
static std::string asTranscript[5]; // napisy na ekranie (widoczne)
*/
static TTranscripts tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie static TTranscripts tranTexts; // obiekt obsługujący stenogramy dźwięków na ekranie
static float4 UITextColor; // base color of UI text static float4 UITextColor; // base color of UI text
static std::string asLang; // domyślny język - http://tools.ietf.org/html/bcp47 static std::string asLang; // domyślny język - http://tools.ietf.org/html/bcp47

View File

@@ -153,74 +153,30 @@ TGroundNode::TGroundNode( TGroundNodeType t ) :
} }
} }
void TGroundNode::InitNormals() // obliczenie wektorów normalnych
{ // obliczenie wektorów normalnych void TGroundNode::InitNormals() {
glm::dvec3 v1, v2, v3, v4, v5;
glm::vec3 n1, n2, n3, n4; glm::dvec3 v1, v2;
glm::vec3 n1;
glm::vec2 t1; glm::vec2 t1;
int i;
switch (iType)
{
case GL_TRIANGLE_STRIP:
v1 = Piece->vertices[0].position - Piece->vertices[1].position;
v2 = Piece->vertices[1].position - Piece->vertices[2].position;
n1 = glm::normalize(glm::cross(v1, v2));
if (Piece->vertices[0].normal == glm::vec3())
Piece->vertices[0].normal = n1;
v3 = Piece->vertices[2].position - Piece->vertices[3].position;
n2 = glm::normalize(glm::cross(v3, v2));
if (Piece->vertices[1].normal == glm::vec3())
Piece->vertices[1].normal = (n1 + n2) * 0.5f;
for ( i = 2; i < iNumVerts - 2; i += 2) for( auto i = 0; i < iNumVerts; i += 3 ) {
{
v4 = Piece->vertices[i - 1].position - Piece->vertices[i].position;
v5 = Piece->vertices[i].position - Piece->vertices[i + 1].position;
n3 = glm::normalize(glm::cross(v3, v4));
n4 = glm::normalize(glm::cross(v5, v4));
if (Piece->vertices[i].normal == glm::vec3())
Piece->vertices[i].normal = (n1 + n2 + n3) / 3.0f;
if (Piece->vertices[i + 1].normal == glm::vec3())
Piece->vertices[i + 1].normal = (n2 + n3 + n4) / 3.0f;
n1 = n3;
n2 = n4;
v3 = v5;
}
if (Piece->vertices[i].normal == glm::vec3())
Piece->vertices[i].normal = (n1 + n2) / 2.0f;
if (i + 1 < iNumVerts)
{
if (Piece->vertices[i + 1].normal == glm::vec3())
Piece->vertices[i + 1].normal = n2;
}
else
WriteLog("odd number of vertices, normals may be wrong!");
break; v1 = Piece->vertices[ i + 0 ].position - Piece->vertices[ i + 1 ].position;
case GL_TRIANGLE_FAN: v2 = Piece->vertices[ i + 1 ].position - Piece->vertices[ i + 2 ].position;
n1 = glm::normalize( glm::cross( v1, v2 ) );
break; if( Piece->vertices[ i + 0 ].normal == glm::vec3() )
case GL_TRIANGLES: Piece->vertices[ i + 0 ].normal = ( n1 );
for (i = 0; i < iNumVerts; i += 3) if( Piece->vertices[ i + 1 ].normal == glm::vec3() )
{ Piece->vertices[ i + 1 ].normal = ( n1 );
v1 = Piece->vertices[i + 0].position - Piece->vertices[i + 1].position; if( Piece->vertices[ i + 2 ].normal == glm::vec3() )
v2 = Piece->vertices[i + 1].position - Piece->vertices[i + 2].position; Piece->vertices[ i + 2 ].normal = ( n1 );
auto c = glm::cross(v1, v2); t1 = glm::vec2(
n1 = glm::length(c) != 0 ? glm::normalize(c) : glm::vec3(); std::floor( Piece->vertices[ i + 0 ].texture.s ),
if( Piece->vertices[i + 0].normal == glm::vec3() ) std::floor( Piece->vertices[ i + 0 ].texture.t ) );
Piece->vertices[i + 0].normal = (n1); Piece->vertices[ i + 1 ].texture -= t1;
if( Piece->vertices[i + 1].normal == glm::vec3() ) Piece->vertices[ i + 2 ].texture -= t1;
Piece->vertices[i + 1].normal = (n1); Piece->vertices[ i + 0 ].texture -= t1;
if( Piece->vertices[i + 2].normal == glm::vec3() )
Piece->vertices[i + 2].normal = (n1);
t1 = glm::vec2(
std::floor( Piece->vertices[ i + 0 ].texture.s ),
std::floor( Piece->vertices[ i + 0 ].texture.t ) );
Piece->vertices[ i + 1 ].texture -= t1;
Piece->vertices[ i + 2 ].texture -= t1;
Piece->vertices[ i + 0 ].texture -= t1;
}
break;
} }
} }
@@ -705,6 +661,42 @@ TGround::GetRect( double x, double z ) {
} }
}; };
// convert tp_terrain model to a series of triangle nodes
void
TGround::convert_terrain( TGroundNode const *Terrain ) {
TSubModel *submodel { nullptr };
for( auto cellindex = 1; cellindex < Terrain->iCount; ++cellindex ) {
// go through all submodels for individual terrain cells...
submodel = Terrain->nNode[ cellindex ].smTerrain;
convert_terrain( submodel );
// if there's more than one group of triangles in the cell they're held as children of the primary submodel
submodel = submodel->ChildGet();
while( submodel != nullptr ) {
convert_terrain( submodel );
submodel = submodel->NextGet();
}
}
}
void
TGround::convert_terrain( TSubModel const *Submodel ) {
auto groundnode = new TGroundNode( GL_TRIANGLES );
Submodel->convert( *groundnode );
if( groundnode->iNumVerts > 0 ) {
// jeśli nie jest pojazdem ostatni dodany dołączamy na końcu nowego
groundnode->nNext = nRootOfType[ groundnode->iType ];
// ustawienie nowego na początku listy
nRootOfType[ groundnode->iType ] = groundnode;
++iNumNodes;
}
else {
delete groundnode;
}
}
double fTrainSetVel = 0; double fTrainSetVel = 0;
double fTrainSetDir = 0; double fTrainSetDir = 0;
double fTrainSetDist = 0; // odległość składu od punktu 1 w stronę punktu 2 double fTrainSetDist = 0; // odległość składu od punktu 1 w stronę punktu 2
@@ -1220,61 +1212,123 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
} }
break; break;
case TP_MODEL: case TP_MODEL: {
if (rmin < 0) #ifdef EU07_USE_OLD_TERRAINCODE
{ if( rmin < 0 ) {
tmp->iType = TP_TERRAIN; tmp->iType = TP_TERRAIN;
tmp->fSquareMinRadius = 0; // to w ogóle potrzebne? tmp->fSquareMinRadius = 0; // to w ogóle potrzebne?
} }
parser->getTokens(3); parser->getTokens( 3 );
*parser >> tmp->pCenter.x >> tmp->pCenter.y >> tmp->pCenter.z; *parser >> tmp->pCenter.x >> tmp->pCenter.y >> tmp->pCenter.z;
parser->getTokens(); parser->getTokens();
*parser >> tf1; *parser >> tf1;
// OlO_EU&KAKISH-030103: obracanie punktow zaczepien w modelu // OlO_EU&KAKISH-030103: obracanie punktow zaczepien w modelu
tmp->pCenter.RotateY(aRotate.y / 180.0 * M_PI); tmp->pCenter.RotateY( aRotate.y / 180.0 * M_PI );
// McZapkie-260402: model tez ma wspolrzedne wzgledne // McZapkie-260402: model tez ma wspolrzedne wzgledne
tmp->pCenter += pOrigin; tmp->pCenter += pOrigin;
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( aRotate.x, tf1 + aRotate.y, aRotate.z ); // dostosowanie do pochylania linii
if( tmp->Model->Load( parser, tmp->iType == TP_TERRAIN ) ) { if( tmp->Model->Load( parser, tmp->iType == TP_TERRAIN ) ) {
// wczytanie modelu, tekstury i stanu świateł... // wczytanie modelu, tekstury i stanu świateł...
tmp->iFlags = tmp->Model->Flags() | 0x200; // ustalenie, czy przezroczysty; flaga usuwania tmp->iFlags = tmp->Model->Flags() | 0x200; // ustalenie, czy przezroczysty; flaga usuwania
} }
else if (tmp->iType != TP_TERRAIN) else if( tmp->iType != TP_TERRAIN ) { // model nie wczytał się - ignorowanie node
{ // model nie wczytał się - ignorowanie node
delete tmp; delete tmp;
tmp = NULL; // nie może być tu return tmp = NULL; // nie może być tu return
break; // nie może być tu return? break; // nie może być tu return?
} }
if (tmp->iType == TP_TERRAIN) if( tmp->iType == TP_TERRAIN ) { // jeśli model jest terenem, trzeba utworzyć dodatkowe obiekty
{ // jeśli model jest terenem, trzeba utworzyć dodatkowe obiekty
// po wczytaniu model ma już utworzone DL albo VBO // po wczytaniu model ma już utworzone DL albo VBO
Global::pTerrainCompact = tmp->Model; // istnieje co najmniej jeden obiekt terenu Global::pTerrainCompact = tmp->Model; // istnieje co najmniej jeden obiekt terenu
tmp->pCenter = Math3D::vector3( 0.0, 0.0, 0.0 ); // enforce placement in the world center tmp->pCenter = Math3D::vector3( 0.0, 0.0, 0.0 ); // enforce placement in the world center
tmp->iCount = Global::pTerrainCompact->TerrainCount() + 1; // zliczenie submodeli tmp->iCount = Global::pTerrainCompact->TerrainCount() + 1; // zliczenie submodeli
tmp->nNode = new TGroundNode[tmp->iCount]; // sztuczne node dla kwadratów tmp->nNode = new TGroundNode[ tmp->iCount ]; // sztuczne node dla kwadratów
tmp->nNode[0].iType = TP_MODEL; // pierwszy zawiera model (dla delete) tmp->nNode[ 0 ].iType = TP_MODEL; // pierwszy zawiera model (dla delete)
tmp->nNode[0].Model = Global::pTerrainCompact; tmp->nNode[ 0 ].Model = Global::pTerrainCompact;
tmp->nNode[0].iFlags = 0x200; // nie wyświetlany, ale usuwany tmp->nNode[ 0 ].iFlags = 0x200; // nie wyświetlany, ale usuwany
for (int i = 1; i < tmp->iCount; ++i) for( int i = 1; i < tmp->iCount; ++i ) { // a reszta to submodele
{ // a reszta to submodele tmp->nNode[ i ].iType = TP_SUBMODEL;
tmp->nNode[i].iType = TP_SUBMODEL; tmp->nNode[ i ].smTerrain = Global::pTerrainCompact->TerrainSquare( i - 1 );
tmp->nNode[i].smTerrain = Global::pTerrainCompact->TerrainSquare(i - 1); tmp->nNode[ i ].iFlags = 0x10; // nieprzezroczyste; nie usuwany
tmp->nNode[i].iFlags = 0x10; // nieprzezroczyste; nie usuwany tmp->nNode[ i ].bVisible = true;
tmp->nNode[i].bVisible = true; tmp->nNode[ i ].pCenter = tmp->pCenter; // nie przesuwamy w inne miejsce
tmp->nNode[i].pCenter = tmp->pCenter; // nie przesuwamy w inne miejsce
} }
} }
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_trackmap.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
} }
} }
// str=Parser->GetNextSymbol().LowerCase(); #else
if( rmin < 0 ) {
// legacy leftover: special case, terrain provided as 3d model
tmp->iType = TP_TERRAIN;
tmp->fSquareMinRadius = 0; // to w ogóle potrzebne?
// we ignore center and rotation for terrain; they should be set to 0 anyway
parser->getTokens( 4 );
tmp->iFlags = 0x200; // flaga usuwania
tmp->Model = new TAnimModel();
if( false == tmp->Model->Load( parser, true ) ) {
delete tmp;
tmp = nullptr;
break;
}
tmp->iFlags |= tmp->Model->Flags(); // ustalenie, czy przezroczysty
tmp->pCenter = Math3D::vector3(); // enforce placement in the world center
// jeśli model jest terenem, trzeba utworzyć dodatkowe obiekty
tmp->iCount = tmp->Model->TerrainCount() + 1; // zliczenie submodeli
Global::pTerrainCompact = tmp->Model;
tmp->nNode = new TGroundNode[ tmp->iCount ]; // sztuczne node dla kwadratów
tmp->nNode[ 0 ].iType = TP_MODEL; // pierwszy zawiera model (dla delete)
tmp->nNode[ 0 ].Model = Global::pTerrainCompact;
tmp->nNode[ 0 ].iFlags = 0x200; // nie wyświetlany, ale usuwany
for( auto i = 1; i < tmp->iCount; ++i ) { // a reszta to submodele
tmp->nNode[ i ].iType = TP_SUBMODEL;
tmp->nNode[ i ].smTerrain = Global::pTerrainCompact->TerrainSquare( i - 1 );
tmp->nNode[ i ].iFlags = 0x10; // nieprzezroczyste; nie usuwany
tmp->nNode[ i ].bVisible = true;
tmp->nNode[ i ].pCenter = tmp->pCenter; // nie przesuwamy w inne miejsce
}
}
else {
// regular 3d model
parser->getTokens( 3 );
*parser
>> tmp->pCenter.x
>> tmp->pCenter.y
>> tmp->pCenter.z;
parser->getTokens();
*parser >> tf1;
// OlO_EU&KAKISH-030103: obracanie punktow zaczepien w modelu
tmp->pCenter.RotateY( glm::radians( aRotate.y ) );
// McZapkie-260402: model tez ma wspolrzedne wzgledne
tmp->pCenter += pOrigin;
tmp->iFlags = 0x200; // flaga usuwania
tmp->Model = new TAnimModel();
tmp->Model->RaAnglesSet( aRotate.x, tf1 + aRotate.y, aRotate.z ); // dostosowanie do pochylania linii
if( false == tmp->Model->Load( parser, false ) ) {
// model nie wczytał się - ignorowanie node
delete tmp;
tmp = nullptr; // nie może być tu return
break; // nie może być tu return?
}
tmp->iFlags |= tmp->Model->Flags(); // ustalenie, czy przezroczysty
if( false == tmp->asName.empty() ) { // jest pusta gdy "none"
// dodanie do wyszukiwarki
if( false == m_trackmap.Add( TP_MODEL, tmp->asName, tmp ) ) {
// przy zdublowaniu wskaźnik zostanie podmieniony w drzewku na późniejszy (zgodność wsteczna)
ErrorLog( "Duplicated model: " + tmp->asName ); // to zgłaszać duplikat
}
}
}
#endif
break; break;
}
// case TP_GEOMETRY : // case TP_GEOMETRY :
case GL_TRIANGLES: case GL_TRIANGLES:
case GL_TRIANGLE_STRIP: case GL_TRIANGLE_STRIP:
@@ -1353,12 +1407,12 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
>> vertex.normal.z >> vertex.normal.z
>> vertex.texture.s >> vertex.texture.s
>> vertex.texture.t; >> vertex.texture.t;
vertex.position = glm::rotateZ( vertex.position, aRotate.z / 180 * M_PI ); vertex.position = glm::rotateZ( vertex.position, glm::radians( aRotate.z ) );
vertex.position = glm::rotateX( vertex.position, aRotate.x / 180 * M_PI ); vertex.position = glm::rotateX( vertex.position, glm::radians( aRotate.x ) );
vertex.position = glm::rotateY( vertex.position, aRotate.y / 180 * M_PI ); vertex.position = glm::rotateY( vertex.position, glm::radians( aRotate.y ) );
vertex.normal = glm::rotateZ( vertex.normal, static_cast<float>( aRotate.z / 180 * M_PI ) ); vertex.normal = glm::rotateZ( vertex.normal, glm::radians<float>( aRotate.z ) );
vertex.normal = glm::rotateX( vertex.normal, static_cast<float>( aRotate.x / 180 * M_PI ) ); vertex.normal = glm::rotateX( vertex.normal, glm::radians<float>( aRotate.x ) );
vertex.normal = glm::rotateY( vertex.normal, static_cast<float>( aRotate.y / 180 * M_PI ) ); vertex.normal = glm::rotateY( vertex.normal, glm::radians<float>( aRotate.y ) );
vertex.position += glm::dvec3{ pOrigin }; vertex.position += glm::dvec3{ pOrigin };
if( true == clamps ) { vertex.texture.s = clamp( vertex.texture.s, 0.001f, 0.999f ); } 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 ); } if( true == clampt ) { vertex.texture.t = clamp( vertex.texture.t, 0.001f, 0.999f ); }
@@ -1487,9 +1541,9 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
*parser *parser
>> vertex.position.y >> vertex.position.y
>> vertex.position.z; >> vertex.position.z;
vertex.position = glm::rotateZ( vertex.position, aRotate.z / 180 * M_PI ); vertex.position = glm::rotateZ( vertex.position, glm::radians( aRotate.z ) );
vertex.position = glm::rotateX( vertex.position, aRotate.x / 180 * M_PI ); vertex.position = glm::rotateX( vertex.position, glm::radians( aRotate.x ) );
vertex.position = glm::rotateY( vertex.position, aRotate.y / 180 * M_PI ); vertex.position = glm::rotateY( vertex.position, glm::radians( aRotate.y ) );
vertex.position += glm::dvec3{ pOrigin }; vertex.position += glm::dvec3{ pOrigin };
// convert all data to gl_lines to allow data merge for matching nodes // convert all data to gl_lines to allow data merge for matching nodes
@@ -1621,7 +1675,8 @@ void TGround::FirstInit()
for (int type = 0; type < TP_LAST; ++type) { for (int type = 0; type < TP_LAST; ++type) {
for (TGroundNode *Current = nRootOfType[type]; Current != nullptr; Current = Current->nNext) { for (TGroundNode *Current = nRootOfType[type]; Current != nullptr; Current = Current->nNext) {
Current->InitNormals(); if( type == GL_TRIANGLES ) { Current->InitNormals(); }
if (Current->iType != TP_DYNAMIC) if (Current->iType != TP_DYNAMIC)
{ // pojazdów w ogóle nie dotyczy dodawanie do mapy { // pojazdów w ogóle nie dotyczy dodawanie do mapy
if( ( type == TP_EVLAUNCH ) if( ( type == TP_EVLAUNCH )
@@ -1629,6 +1684,7 @@ void TGround::FirstInit()
// dodanie do globalnego obiektu // dodanie do globalnego obiektu
srGlobal.NodeAdd( Current ); srGlobal.NodeAdd( Current );
} }
#ifdef EU07_USE_OLD_TERRAINCODE
else if (type == TP_TERRAIN) { else if (type == TP_TERRAIN) {
// specjalne przetwarzanie terenu wczytanego z pliku E3D // specjalne przetwarzanie terenu wczytanego z pliku E3D
TGroundRect *gr; TGroundRect *gr;
@@ -1641,6 +1697,7 @@ void TGround::FirstInit()
gr->nTerrain = Current->nNode + j; // zapamiętanie gr->nTerrain = Current->nNode + j; // zapamiętanie
} }
} }
#endif
else { else {
TSubRect *targetcell { nullptr }; TSubRect *targetcell { nullptr };
// test whether we can add the node to a ground cell, or a subcell // test whether we can add the node to a ground cell, or a subcell
@@ -1744,6 +1801,15 @@ bool TGround::Init(std::string File)
} }
break; break;
} }
#ifndef EU07_SCENERY_EDITOR
case TP_TERRAIN: {
// convert legacy terrain model to a series of triangle nodes, to take advantage of camera-centric render and geometry merging
// NOTE: this leaves us with a large model we don't use loaded and taking space. it'll sort of solve itself when the binary scenery file is in place
convert_terrain( LastNode );
SafeDelete( LastNode );
Global::pTerrainCompact = nullptr;
}
#endif
default: { default: {
break; break;
} }
@@ -2121,8 +2187,10 @@ bool TGround::Init(std::string File)
if (!bInitDone) if (!bInitDone)
FirstInit(); // jeśli nie było w scenerii FirstInit(); // jeśli nie było w scenerii
#ifdef EU07_USE_OLD_TERRAINCODE
if (Global::pTerrainCompact) if (Global::pTerrainCompact)
TerrainWrite(); // Ra: teraz można zapisać teren w jednym pliku TerrainWrite(); // Ra: teraz można zapisać teren w jednym pliku
#endif
Global::iPause &= ~0x10; // koniec pauzy wczytywania Global::iPause &= ~0x10; // koniec pauzy wczytywania
return true; return true;
} }
@@ -3494,18 +3562,6 @@ void
TGround::Update_Lights() { TGround::Update_Lights() {
m_lights.update(); m_lights.update();
// arrange the light array from closest to farthest from current position of the camera
auto const camera = Global::pCameraPosition;
std::sort(
m_lights.data.begin(),
m_lights.data.end(),
[&]( light_array::light_record const &Left, light_array::light_record const &Right ) {
// move lights which are off at the end...
if( Left.intensity == 0.0f ) { return false; }
if( Right.intensity == 0.0f ) { return true; }
// ...otherwise prefer closer and/or brigher light sources
return ((camera - Left.position).LengthSquared() * (1.0f - Left.intensity)) < ((camera - Right.position).LengthSquared() * (1.0f - Right.intensity));
} );
} }
// Winger 170204 - szukanie trakcji nad pantografami // Winger 170204 - szukanie trakcji nad pantografami

View File

@@ -175,10 +175,6 @@ class TSubRect : /*public Resource,*/ public CMesh
TTrack **tTracks = nullptr; // tory do renderowania pojazdów TTrack **tTracks = nullptr; // tory do renderowania pojazdów
protected: protected:
TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji TTrack *tTrackAnim = nullptr; // obiekty do przeliczenia animacji
#ifdef EU07_USE_OLD_RENDERCODE
TGroundNode *nRootMesh = nullptr; // obiekty renderujące wg tekstury (wtórne, lista po nNext2)
TGroundNode *nMeshed = nullptr; // lista obiektów dla których istnieją obiekty renderujące grupowo
#endif
public: public:
TGroundNode *nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2) TGroundNode *nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2)
TGroundNode *nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3) TGroundNode *nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3)
@@ -333,6 +329,9 @@ class TGround
void TrackJoin(TGroundNode *Current); void TrackJoin(TGroundNode *Current);
private: private:
// convert tp_terrain model to a series of triangle nodes
void convert_terrain( TGroundNode const *Terrain );
void convert_terrain( TSubModel const *Submodel );
void RaTriangleDivider(TGroundNode *node); void RaTriangleDivider(TGroundNode *node);
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam); void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);

View File

@@ -384,14 +384,14 @@ struct TBoilerType {
}; };
/*rodzaj odbieraka pradu*/ /*rodzaj odbieraka pradu*/
struct TCurrentCollector { struct TCurrentCollector {
long CollectorsNo{ 0 }; //musi być tu, bo inaczej się kopie long CollectorsNo; //musi być tu, bo inaczej się kopie
double MinH{ 0.0 }; double MaxH{ 0.0 }; //zakres ruchu pantografu, nigdzie nie używany double MinH; double MaxH; //zakres ruchu pantografu, nigdzie nie używany
double CSW{ 0.0 }; //szerokość części roboczej (styku) ślizgacza double CSW; //szerokość części roboczej (styku) ślizgacza
double MinV{ 0.0 }; double MaxV{ 0.0 }; //minimalne i maksymalne akceptowane napięcie double MinV; double MaxV; //minimalne i maksymalne akceptowane napięcie
double OVP{ 0.0 }; //czy jest przekaznik nadnapieciowy double OVP; //czy jest przekaznik nadnapieciowy
double InsetV{ 0.0 }; //minimalne napięcie wymagane do załączenia double InsetV; //minimalne napięcie wymagane do załączenia
double MinPress{ 0.0 }; //minimalne ciśnienie do załączenia WS double MinPress; //minimalne ciśnienie do załączenia WS
double MaxPress{ 0.0 }; //maksymalne ciśnienie za reduktorem double MaxPress; //maksymalne ciśnienie za reduktorem
//inline TCurrentCollector() { //inline TCurrentCollector() {
// CollectorsNo = 0; // CollectorsNo = 0;
// MinH, MaxH, CSW, MinV, MaxV = 0.0; // MinH, MaxH, CSW, MinV, MaxV = 0.0;
@@ -624,14 +624,14 @@ public:
bool Signalling = false; /*Czy jest zalaczona sygnalizacja hamowania ostatniego wagonu*/ bool Signalling = false; /*Czy jest zalaczona sygnalizacja hamowania ostatniego wagonu*/
bool DoorSignalling = false; /*Czy jest zalaczona sygnalizacja blokady drzwi*/ bool DoorSignalling = false; /*Czy jest zalaczona sygnalizacja blokady drzwi*/
bool Radio = true; /*Czy jest zalaczony radiotelefon*/ bool Radio = true; /*Czy jest zalaczony radiotelefon*/
double NominalBatteryVoltage = 0.0; /*Winger - baterie w elektrykach*/ float NominalBatteryVoltage = 0.f; /*Winger - baterie w elektrykach*/
TDimension Dim; /*wymiary*/ TDimension Dim; /*wymiary*/
double Cx = 0.0; /*wsp. op. aerodyn.*/ double Cx = 0.0; /*wsp. op. aerodyn.*/
double Floor = 0.96; //poziom podłogi dla ładunków float Floor = 0.96f; //poziom podłogi dla ładunków
double WheelDiameter = 1.0; /*srednica kol napednych*/ float WheelDiameter = 1.f; /*srednica kol napednych*/
double WheelDiameterL = 0.9; //Ra: srednica kol tocznych przednich float WheelDiameterL = 0.9f; //Ra: srednica kol tocznych przednich
double WheelDiameterT = 0.9; //Ra: srednica kol tocznych tylnych float WheelDiameterT = 0.9f; //Ra: srednica kol tocznych tylnych
double TrackW = 1.435; /*nominalna szerokosc toru [m]*/ float TrackW = 1.435f; /*nominalna szerokosc toru [m]*/
double AxleInertialMoment = 0.0; /*moment bezwladnosci zestawu kolowego*/ double AxleInertialMoment = 0.0; /*moment bezwladnosci zestawu kolowego*/
std::string AxleArangement; /*uklad osi np. Bo'Bo' albo 1'C*/ std::string AxleArangement; /*uklad osi np. Bo'Bo' albo 1'C*/
int NPoweredAxles = 0; /*ilosc osi napednych liczona z powyzszego*/ int NPoweredAxles = 0; /*ilosc osi napednych liczona z powyzszego*/

View File

@@ -8178,7 +8178,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
else if (Command == "PantRear") /*Winger 160204, ABu 310105 i 030305*/ else if (Command == "PantRear") /*Winger 160204, ABu 310105 i 030305*/
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if ((TrainType == dt_EZT)) if ((TrainType == dt_EZT))
{ /*'ezt'*/ { //'ezt'
if ((CValue1 == 1)) if ((CValue1 == 1))
{ {
PantRearUp = true; PantRearUp = true;
@@ -8191,9 +8191,9 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
} }
} }
else else
{ /*nie 'ezt'*/ { //nie 'ezt'
if ((CValue1 == 1)) if ((CValue1 == 1))
/*if ostatni polaczony sprz. sterowania*/ //if ostatni polaczony sprz. sterowania
if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) || if ((TestFlag(Couplers[1].CouplingFlag, ctrain_controll) && (CValue2 == 1)) ||
(TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1))) (TestFlag(Couplers[0].CouplingFlag, ctrain_controll) && (CValue2 == -1)))
{ {

View File

@@ -19,6 +19,7 @@ Copyright (C) 2007-2014 Maciej Cierniak
bool DebugModeFlag = false; bool DebugModeFlag = false;
bool FreeFlyModeFlag = false; bool FreeFlyModeFlag = false;
bool DebugCameraFlag = false;
double Max0R(double x1, double x2) double Max0R(double x1, double x2)
{ {

View File

@@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/.
extern bool DebugModeFlag; extern bool DebugModeFlag;
extern bool FreeFlyModeFlag; extern bool FreeFlyModeFlag;
extern bool DebugCameraFlag;
/*funkcje matematyczne*/ /*funkcje matematyczne*/
double Max0R(double x1, double x2); double Max0R(double x1, double x2);

View File

@@ -17,64 +17,45 @@ http://mozilla.org/MPL/2.0/.
#include "MdlMngr.h" #include "MdlMngr.h"
#include "Globals.h" #include "Globals.h"
#include "Logs.h"
#include "McZapkie/mctools.h" #include "McZapkie/mctools.h"
//#define SeekFiles std::string("*.t3d") // wczytanie modelu do kontenerka
TModel3d *
TMdlContainer::LoadModel(std::string const &Name, bool const Dynamic) {
TModel3d * TMdlContainer::LoadModel(std::string const &NewName, bool dynamic) Model = std::make_shared<TModel3d>();
{ // wczytanie modelu do kontenerka if( true == Model->LoadFromFile( Name, Dynamic ) ) {
SafeDelete(Model); m_name = Name;
Name = NewName; return Model.get();
Model = new TModel3d(); }
if (!Model->LoadFromFile(Name, dynamic)) // np. "models\\pkp/head1-y.t3d" else {
SafeDelete(Model); m_name.clear();
return Model; Model = nullptr;
}; return nullptr;
}
TMdlContainer *TModelsManager::Models; };
int TModelsManager::Count;
int const MAX_MODELS = 1000; TModelsManager::modelcontainer_sequence TModelsManager::m_models;
TModelsManager::stringmodelcontainerindex_map TModelsManager::m_modelsmap;
void TModelsManager::Init()
{ // wczytanie modelu do tablicy
Models = new TMdlContainer[MAX_MODELS]; TModel3d *
Count = 0; TModelsManager::LoadModel(std::string const &Name, bool dynamic) {
}
/* m_models.emplace_back();
TModelsManager::TModelsManager() auto model = m_models.back().LoadModel( Name, dynamic );
{ if( model != nullptr ) {
// Models= NULL; m_modelsmap.emplace( Name, m_models.size() - 1 );
Models= new TMdlContainer[MAX_MODELS]; return model;
Count= 0; }
}; else {
m_models.pop_back();
TModelsManager::~TModelsManager() return nullptr;
{
Free();
};
*/
void TModelsManager::Free()
{
delete[] Models;
Models = nullptr;
}
TModel3d * TModelsManager::LoadModel(std::string const &Name, bool dynamic)
{ // wczytanie modelu do tablicy
TModel3d *mdl = NULL;
if (Count >= MAX_MODELS)
Error("FIXME: Too many models, program will now crash :)");
else
{
mdl = Models[Count].LoadModel(Name, dynamic);
if (mdl)
Count++; // jeśli błąd wczytania modelu, to go nie wliczamy
} }
return mdl;
} }
TModel3d * TModelsManager::GetModel(std::string const &Name, bool dynamic) TModel3d *
TModelsManager::GetModel(std::string const &Name, bool const Dynamic)
{ // model może być we wpisie "node...model" albo "node...dynamic", a także być dodatkowym w dynamic { // model może być we wpisie "node...model" albo "node...dynamic", a także być dodatkowym w dynamic
// (kabina, wnętrze, ładunek) // (kabina, wnętrze, ładunek)
// dla "node...dynamic" mamy podaną ścieżkę w "\dynamic\" i musi być co najmniej 1 poziom, zwkle // dla "node...dynamic" mamy podaną ścieżkę w "\dynamic\" i musi być co najmniej 1 poziom, zwkle
@@ -97,53 +78,10 @@ TModel3d * TModelsManager::GetModel(std::string const &Name, bool dynamic)
// - niebo animowane, ścieżka brana ze wpisu, tekstury nieokreślone // - niebo animowane, ścieżka brana ze wpisu, tekstury nieokreślone
// - wczytanie modelu animowanego - Init() - sprawdzić // - wczytanie modelu animowanego - Init() - sprawdzić
std::string buf; std::string buf;
std::string buftp = Global::asCurrentTexturePath; // zapamiętanie aktualnej ścieżki do tekstur, std::string const buftp = Global::asCurrentTexturePath; // zapamiętanie aktualnej ścieżki do tekstur,
// bo będzie tyczmasowo zmieniana
/*
// Ra: niby tak jest lepiej, ale działa gorzej, więc przywrócone jest oryginalne
//nawet jeśli model będzie pobrany z tablicy, to trzeba ustalić ścieżkę dla tekstur
if (dynamic) //na razie tak, bo nie wiadomo, jaki może mieć wpływ na pozostałe modele
{//dla pojazdów podana jest zawsze pełna ścieżka do modelu
strcpy(buf,Name);
if (strchr(Name,'/')!=NULL)
{//pobieranie tekstur z katalogu, w którym jest model
Global::asCurrentTexturePath=Global::asCurrentTexturePath+AnsiString(Name);
Global::asCurrentTexturePath.Delete(Global::asCurrentTexturePath.Pos("/")+1,Global::asCurrentTexturePath.Length());
}
}
else
{//dla modeli scenerii trzeba ustalić ścieżkę
if (strchr(Name,'\\')==NULL)
{//jeśli nie ma lewego ukośnika w ścieżce, a jest prawy, to zmienić ścieżkę dla tekstur na tę
z modelem
strcpy(buf,"models\\"); //Ra: było by lepiej katalog dodać w parserze
//strcpy(buf,"scenery\\"); //Ra: było by lepiej katalog dodać w parserze
strcat(buf,Name);
if (strchr(Name,'/')!=NULL)
{//jeszcze musi być prawy ukośnik
Global::asCurrentTexturePath=Global::asCurrentTexturePath+AnsiString(Name);
Global::asCurrentTexturePath.Delete(Global::asCurrentTexturePath.Pos("/")+1,Global::asCurrentTexturePath.Length());
}
}
else
{//jeśli jest lewy ukośnik, to ścieżkę do tekstur zmienić tylko dla pojazdów
strcpy(buf,Name);
}
}
StrLower(buf);
for (int i=0;i<Count;i++)
{//bezsensowne przeszukanie tabeli na okoliczność wystąpienia modelu
if (strcmp(buf,Models[i].Name)==0)
{
Global::asCurrentTexturePath=buftp; //odtworzenie ścieżki do tekstur
return (Models[i].Model); //model znaleziony
}
};
*/
if( Name.find('\\') == std::string::npos ) if( Name.find('\\') == std::string::npos )
{ {
buf = "models\\"; // Ra: było by lepiej katalog dodać w parserze buf = "models\\" + Name; // Ra: było by lepiej katalog dodać w parserze
buf.append( Name );
if( Name.find( '/') != std::string::npos) if( Name.find( '/') != std::string::npos)
{ {
Global::asCurrentTexturePath = Global::asCurrentTexturePath + Name; Global::asCurrentTexturePath = Global::asCurrentTexturePath + Name;
@@ -154,43 +92,27 @@ TModel3d * TModelsManager::GetModel(std::string const &Name, bool dynamic)
else else
{ {
buf = Name; buf = Name;
if (dynamic) // na razie tak, bo nie wiadomo, jaki może mieć wpływ na pozostałe modele if( Dynamic ) {
if (Name.find( '/') != std::string::npos) // na razie tak, bo nie wiadomo, jaki może mieć wpływ na pozostałe modele
{ // pobieranie tekstur z katalogu, w którym jest model if( Name.find( '/' ) != std::string::npos ) { // pobieranie tekstur z katalogu, w którym jest model
Global::asCurrentTexturePath = Global::asCurrentTexturePath + Name; Global::asCurrentTexturePath = Global::asCurrentTexturePath + Name;
Global::asCurrentTexturePath.erase(Global::asCurrentTexturePath.find("/") + 1, Global::asCurrentTexturePath.erase(
Global::asCurrentTexturePath.length() - 1); Global::asCurrentTexturePath.find( "/" ) + 1,
Global::asCurrentTexturePath.length() - 1 );
} }
}
} }
buf = ToLower( buf ); buf = ToLower( buf );
for (int i = 0; i < Count; ++i)
{ auto const lookup = m_modelsmap.find( buf );
if ( buf == Models[i].Name ) if( lookup != m_modelsmap.end() ) {
{ Global::asCurrentTexturePath = buftp;
Global::asCurrentTexturePath = buftp; return ( m_models[ lookup->second ].Model.get() );
return (Models[i].Model); }
}
}; auto model = LoadModel(buf, Dynamic); // model nie znaleziony, to wczytać
TModel3d *tmpModel = LoadModel(buf, dynamic); // model nie znaleziony, to wczytać
Global::asCurrentTexturePath = buftp; // odtworzenie ścieżki do tekstur Global::asCurrentTexturePath = buftp; // odtworzenie ścieżki do tekstur
return (tmpModel); // NULL jeśli błąd return model; // NULL jeśli błąd
}; };
/*
TModel3d TModelsManager::GetModel(char *Name, AnsiString asReplacableTexture)
{
GLuint ReplacableTextureID= 0;
TModel3d NewModel;
NewModel= *GetNextModel(Name);
if (asReplacableTexture!=AnsiString("none"))
ReplacableTextureID= TTexturesManager::GetTextureID(asReplacableTexture.c_str());
NewModel.ReplacableSkinID=ReplacableTextureID;
return NewModel;
};
*/
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -9,33 +9,28 @@ http://mozilla.org/MPL/2.0/.
#pragma once #pragma once
#include "Model3d.h" #include "Model3d.h"
#include "usefull.h"
class TMdlContainer class TMdlContainer {
{
friend class TModelsManager; friend class TModelsManager;
~TMdlContainer() private:
{ TModel3d *LoadModel( std::string const &Name, bool const Dynamic );
delete Model; std::shared_ptr<TModel3d> Model { nullptr };
}; std::string m_name;
TModel3d * LoadModel(std::string const &NewName, bool dynamic);
TModel3d *Model{ nullptr };
std::string Name;
}; };
class TModelsManager // klasa statyczna, nie ma obiektu
{ // klasa statyczna, nie ma obiektu class TModelsManager {
private: // types:
static TMdlContainer *Models; typedef std::deque<TMdlContainer> modelcontainer_sequence;
static int Count; typedef std::unordered_map<std::string, modelcontainer_sequence::size_type> stringmodelcontainerindex_map;
static TModel3d * LoadModel(std::string const &Name, bool dynamic); // members:
static modelcontainer_sequence m_models;
public: static stringmodelcontainerindex_map m_modelsmap;
// TModelsManager(); // methods:
// ~TModelsManager(); static TModel3d *LoadModel( std::string const &Name, bool const Dynamic );
static void Init(); public:
static void Free();
// McZapkie: dodalem sciezke, notabene Path!=Patch :) // McZapkie: dodalem sciezke, notabene Path!=Patch :)
static TModel3d * GetModel(std::string const &Name, bool dynamic = false); static TModel3d *GetModel( std::string const &Name, bool dynamic = false );
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -19,6 +19,7 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
#include "logs.h" #include "logs.h"
#include "mczapkie/mctools.h" #include "mczapkie/mctools.h"
#include "Usefull.h" #include "Usefull.h"
#include "ground.h"
#include "renderer.h" #include "renderer.h"
#include "Timer.h" #include "Timer.h"
#include "mtable.h" #include "mtable.h"
@@ -428,7 +429,9 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
std::vector<unsigned int> sg; sg.resize( facecount ); // maski przynależności trójkątów do powierzchni std::vector<unsigned int> sg; sg.resize( facecount ); // maski przynależności trójkątów do powierzchni
std::vector<int> wsp; wsp.resize( iNumVerts );// z którego wierzchołka kopiować wektor normalny std::vector<int> wsp; wsp.resize( iNumVerts );// z którego wierzchołka kopiować wektor normalny
int maska = 0; int maska = 0;
int rawvertexcount = 0; // used to keep track of vertex indices in source file
for (int i = 0; i < iNumVerts; ++i) { for (int i = 0; i < iNumVerts; ++i) {
++rawvertexcount;
// Ra: z konwersją na układ scenerii - będzie wydajniejsze wyświetlanie // Ra: z konwersją na układ scenerii - będzie wydajniejsze wyświetlanie
wsp[i] = -1; // wektory normalne nie są policzone dla tego wierzchołka wsp[i] = -1; // wektory normalne nie są policzone dla tego wierzchołka
if ((i % 3) == 0) { if ((i % 3) == 0) {
@@ -465,7 +468,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
--facecount; // o jeden trójkąt mniej --facecount; // o jeden trójkąt mniej
iNumVerts -= 3; // czyli o 3 wierzchołki iNumVerts -= 3; // czyli o 3 wierzchołki
i -= 3; // wczytanie kolejnego w to miejsce i -= 3; // wczytanie kolejnego w to miejsce
WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(i) + "-" + std::to_string(i+2)); WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(rawvertexcount-2) + "-" + std::to_string(rawvertexcount));
} }
if (i > 0) { if (i > 0) {
// jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać // jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać
@@ -1035,7 +1038,7 @@ void TSubModel::RaAnimation(TAnimType a)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TSubModel::serialize_geometry( std::ostream &Output ) { void TSubModel::serialize_geometry( std::ostream &Output ) const {
if( Child ) { if( Child ) {
Child->serialize_geometry( Output ); Child->serialize_geometry( Output );
@@ -1074,6 +1077,65 @@ TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &
Next->create_geometry( Dataoffset, Bank ); Next->create_geometry( Dataoffset, Bank );
} }
// places contained geometry in provided ground node
void
TSubModel::convert( TGroundNode &Groundnode ) const {
Groundnode.asName = pName;
Groundnode.Ambient = f4Ambient;
Groundnode.Diffuse = f4Diffuse;
Groundnode.Specular = f4Specular;
Groundnode.TextureID = TextureID;
Groundnode.iFlags = (
( true == GfxRenderer.Texture( TextureID ).has_alpha ) ?
0x20 :
0x10 );
if( m_geometry == NULL ) { return; }
std::size_t vertexcount { 0 };
std::vector<TGroundVertex> importedvertices;
TGroundVertex vertex, vertex1, vertex2;
for( auto const &sourcevertex : GfxRenderer.Vertices( m_geometry ) ) {
vertex.position = sourcevertex.position;
vertex.normal = sourcevertex.normal;
vertex.texture = sourcevertex.texture;
if( vertexcount == 0 ) { vertex1 = vertex; }
else if( vertexcount == 1 ) { vertex2 = vertex; }
else if( vertexcount >= 2 ) {
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
importedvertices.emplace_back( vertex1 );
importedvertices.emplace_back( vertex2 );
importedvertices.emplace_back( vertex );
}
}
++vertexcount;
if( vertexcount > 2 ) { vertexcount = 0; } // start new triangle if needed
}
if( Groundnode.Piece == nullptr ) {
Groundnode.Piece = new piece_node();
}
Groundnode.iNumVerts = importedvertices.size();
if( Groundnode.iNumVerts > 0 ) {
Groundnode.Piece->vertices.swap( importedvertices );
for( auto const &vertex : Groundnode.Piece->vertices ) {
Groundnode.pCenter += vertex.position;
}
Groundnode.pCenter /= Groundnode.iNumVerts;
double r { 0.0 };
double tf;
for( auto const &vertex : Groundnode.Piece->vertices ) {
tf = glm::length2( vertex.position - glm::dvec3{ Groundnode.pCenter } );
if( tf > r )
r = tf;
}
Groundnode.fSquareRadius += r;
}
}
// NOTE: leftover from static distance factor adjustment. // NOTE: leftover from static distance factor adjustment.
// TODO: get rid of it, once we have the dynamic adjustment code in place // TODO: get rid of it, once we have the dynamic adjustment code in place
void TSubModel::AdjustDist() void TSubModel::AdjustDist()
@@ -1665,16 +1727,22 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
pName = ""; pName = "";
if (iTexture > 0) if (iTexture > 0)
{ // obsługa stałej tekstury { // obsługa stałej tekstury
pTexture = t->at(iTexture); if( iTexture < t->size() ) {
if (pTexture.find_last_of("/\\") == std::string::npos) pTexture = t->at( iTexture );
pTexture.insert(0, Global::asCurrentTexturePath); if( pTexture.find_last_of( "/\\" ) == std::string::npos )
TextureID = GfxRenderer.Fetch_Texture(pTexture); pTexture.insert( 0, Global::asCurrentTexturePath );
if( ( iFlags & 0x30 ) == 0 ) { TextureID = GfxRenderer.Fetch_Texture( pTexture );
// texture-alpha based fallback if for some reason we don't have opacity flag set yet if( ( iFlags & 0x30 ) == 0 ) {
iFlags |= // texture-alpha based fallback if for some reason we don't have opacity flag set yet
( GfxRenderer.Texture( TextureID ).has_alpha ? iFlags |=
0x20 : ( GfxRenderer.Texture( TextureID ).has_alpha ?
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta 0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
}
}
else {
ErrorLog( "Bad model: reference to non-existent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ) );
TextureID = NULL;
} }
} }
else else
@@ -1853,17 +1921,3 @@ TSubModel *TModel3d::TerrainSquare(int n)
r->UnFlagNext(); // blokowanie wyświetlania po Next głównej listy r->UnFlagNext(); // blokowanie wyświetlania po Next głównej listy
return r; return r;
}; };
#ifdef EU07_USE_OLD_RENDERCODE
void TModel3d::TerrainRenderVBO(int n)
{ // renderowanie terenu z VBO
::glPushMatrix();
::glTranslated( -Global::pCameraPosition.x, -Global::pCameraPosition.y, -Global::pCameraPosition.z );
TSubModel *r = Root;
while( r ) {
if( r->iVisible == n ) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
GfxRenderer.Render( r ); // sub kolejne (Next) się nie wyrenderują
r = r->NextGet();
}
::glPopMatrix();
};
#endif

View File

@@ -50,6 +50,8 @@ enum TAnimType // rodzaj animacji
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
}; };
class TGroundNode;
class TSubModel class TSubModel
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów { // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
//m7todo: zrobić normalną serializację //m7todo: zrobić normalną serializację
@@ -213,7 +215,9 @@ public:
std::vector<std::string>&, std::vector<std::string>&,
std::vector<std::string>&, std::vector<std::string>&,
std::vector<float4x4>&); std::vector<float4x4>&);
void serialize_geometry( std::ostream &Output ); void serialize_geometry( std::ostream &Output ) const;
// places contained geometry in provided ground node
void convert( TGroundNode &Groundnode ) const;
}; };

View File

@@ -110,7 +110,7 @@ private:
std::chrono::nanoseconds const m_unusedresourcetimetolive; std::chrono::nanoseconds const m_unusedresourcetimetolive;
typename Container_::size_type const m_unusedresourcesweepsize; typename Container_::size_type const m_unusedresourcesweepsize;
std::string const m_resourcename; std::string const m_resourcename;
typename Container_ &m_container; Container_ &m_container;
typename Container_::size_type m_resourcesweepindex { 0 }; typename Container_::size_type m_resourcesweepindex { 0 };
std::chrono::steady_clock::time_point m_resourcetimestamp { std::chrono::steady_clock::now() }; std::chrono::steady_clock::time_point m_resourcetimestamp { std::chrono::steady_clock::now() };
}; };

View File

@@ -592,10 +592,7 @@ opengl_texture::create() {
} }
} }
data.swap( std::vector<char>() ); // TBD, TODO: keep the texture data if we start doing some gpu data cleaning down the road data = std::vector<char>();
/*
data_state = resource_state::none;
*/
data_state = resource_state::none; data_state = resource_state::none;
is_ready = true; is_ready = true;
} }
@@ -609,8 +606,6 @@ opengl_texture::release( bool const Backup ) {
if( id == -1 ) { return; } if( id == -1 ) { return; }
assert( is_ready );
if( true == Backup ) { if( true == Backup ) {
// query texture details needed to perform the backup... // query texture details needed to perform the backup...
::glBindTexture( GL_TEXTURE_2D, id ); ::glBindTexture( GL_TEXTURE_2D, id );
@@ -914,7 +909,7 @@ texture_manager::info() const {
} }
return return
"Textures: " "; textures: "
#ifdef EU07_DEFERRED_TEXTURE_UPLOAD #ifdef EU07_DEFERRED_TEXTURE_UPLOAD
+ std::to_string( readytexturecount ) + std::to_string( readytexturecount )
+ " (" + " ("

View File

@@ -1368,10 +1368,6 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
Train->mvControlled->PantFrontSP = false; Train->mvControlled->PantFrontSP = false;
if( Train->mvControlled->PantFront( true ) ) { if( Train->mvControlled->PantFront( true ) ) {
if( Train->mvControlled->PantFrontStart != 1 ) { if( Train->mvControlled->PantFrontStart != 1 ) {
#ifdef EU07_USE_OLD_CONTROLSOUNDS
// sound feedback
Train->play_sound( Train->dsbSwitch );
#endif
// visual feedback // visual feedback
if( Train->ggPantFrontButton.SubModel ) if( Train->ggPantFrontButton.SubModel )
Train->ggPantFrontButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggPantFrontButton.UpdateValue( 1.0, Train->dsbSwitch );
@@ -1404,10 +1400,6 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
Train->mvControlled->PantFrontSP = false; Train->mvControlled->PantFrontSP = false;
if( false == Train->mvControlled->PantFront( false ) ) { if( false == Train->mvControlled->PantFront( false ) ) {
if( Train->mvControlled->PantFrontStart != 0 ) { if( Train->mvControlled->PantFrontStart != 0 ) {
#ifdef EU07_USE_OLD_CONTROLSOUNDS
// sound feedback
Train->play_sound( Train->dsbSwitch );
#endif
// visual feedback // visual feedback
if( Train->ggPantFrontButton.SubModel ) if( Train->ggPantFrontButton.SubModel )
Train->ggPantFrontButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantFrontButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -1429,11 +1421,6 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// impulse switches return automatically to neutral position // impulse switches return automatically to neutral position
if( Train->mvOccupied->PantSwitchType == "impulse" ) { if( Train->mvOccupied->PantSwitchType == "impulse" ) {
#ifdef EU07_USE_OLD_CONTROLSOUNDS
if( Train->ggPantFrontButton.GetValue() > 0.35 ) {
Train->play_sound( Train->dsbSwitch );
}
#endif
if( Train->ggPantFrontButton.SubModel ) if( Train->ggPantFrontButton.SubModel )
Train->ggPantFrontButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantFrontButton.UpdateValue( 0.0, Train->dsbSwitch );
// NOTE: currently we animate the selectable pantograph control based on standard key presses // NOTE: currently we animate the selectable pantograph control based on standard key presses
@@ -1441,11 +1428,6 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
if( Train->ggPantSelectedButton.SubModel ) if( Train->ggPantSelectedButton.SubModel )
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
// also the switch off button, in cabs which have it // also the switch off button, in cabs which have it
#ifdef EU07_USE_OLD_CONTROLSOUNDS
if( Train->ggPantFrontButtonOff.GetValue() > 0.35 ) {
Train->play_sound( Train->dsbSwitch );
}
#endif
if( Train->ggPantFrontButtonOff.SubModel ) if( Train->ggPantFrontButtonOff.SubModel )
Train->ggPantFrontButtonOff.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantFrontButtonOff.UpdateValue( 0.0, Train->dsbSwitch );
if( Train->ggPantSelectedDownButton.SubModel ) { if( Train->ggPantSelectedDownButton.SubModel ) {
@@ -1466,10 +1448,6 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
Train->mvControlled->PantRearSP = false; Train->mvControlled->PantRearSP = false;
if( Train->mvControlled->PantRear( true ) ) { if( Train->mvControlled->PantRear( true ) ) {
if( Train->mvControlled->PantRearStart != 1 ) { if( Train->mvControlled->PantRearStart != 1 ) {
#ifdef EU07_USE_OLD_CONTROLSOUNDS
// sound feedback
Train->play_sound( Train->dsbSwitch );
#endif
// visual feedback // visual feedback
if( Train->ggPantRearButton.SubModel ) if( Train->ggPantRearButton.SubModel )
Train->ggPantRearButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggPantRearButton.UpdateValue( 1.0, Train->dsbSwitch );
@@ -1502,10 +1480,6 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
Train->mvControlled->PantRearSP = false; Train->mvControlled->PantRearSP = false;
if( false == Train->mvControlled->PantRear( false ) ) { if( false == Train->mvControlled->PantRear( false ) ) {
if( Train->mvControlled->PantRearStart != 0 ) { if( Train->mvControlled->PantRearStart != 0 ) {
#ifdef EU07_USE_OLD_CONTROLSOUNDS
// sound feedback
Train->play_sound( Train->dsbSwitch );
#endif
// visual feedback // visual feedback
if( Train->ggPantRearButton.SubModel ) if( Train->ggPantRearButton.SubModel )
Train->ggPantRearButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantRearButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -1527,11 +1501,6 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// impulse switches return automatically to neutral position // impulse switches return automatically to neutral position
if( Train->mvOccupied->PantSwitchType == "impulse" ) { if( Train->mvOccupied->PantSwitchType == "impulse" ) {
#ifdef EU07_USE_OLD_CONTROLSOUNDS
if( Train->ggPantRearButton.GetValue() > 0.35 ) {
Train->play_sound( Train->dsbSwitch );
}
#endif
if( Train->ggPantRearButton.SubModel ) if( Train->ggPantRearButton.SubModel )
Train->ggPantRearButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantRearButton.UpdateValue( 0.0, Train->dsbSwitch );
// NOTE: currently we animate the selectable pantograph control based on standard key presses // NOTE: currently we animate the selectable pantograph control based on standard key presses
@@ -1539,11 +1508,6 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
if( Train->ggPantSelectedButton.SubModel ) if( Train->ggPantSelectedButton.SubModel )
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
// also the switch off button, in cabs which have it // also the switch off button, in cabs which have it
#ifdef EU07_USE_OLD_CONTROLSOUNDS
if( Train->ggPantRearButtonOff.GetValue() > 0.35 ) {
Train->play_sound( Train->dsbSwitch );
}
#endif
if( Train->ggPantRearButtonOff.SubModel ) if( Train->ggPantRearButtonOff.SubModel )
Train->ggPantRearButtonOff.UpdateValue( 0.0, Train->dsbSwitch ); Train->ggPantRearButtonOff.UpdateValue( 0.0, Train->dsbSwitch );
if( Train->ggPantSelectedDownButton.SubModel ) { if( Train->ggPantSelectedDownButton.SubModel ) {

View File

@@ -15,7 +15,6 @@ http://mozilla.org/MPL/2.0/.
#include "Gauge.h" #include "Gauge.h"
#include "Spring.h" #include "Spring.h"
#include "AdvSound.h" #include "AdvSound.h"
#include "FadeSound.h"
#include "PyInt.h" #include "PyInt.h"
#include "command.h" #include "command.h"

128
World.cpp
View File

@@ -32,8 +32,6 @@ http://mozilla.org/MPL/2.0/.
#include "uilayer.h" #include "uilayer.h"
#include "translation.h" #include "translation.h"
//#define EU07_USE_DEBUG_SHADOWMAP
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
TDynamicObject *Controlled = NULL; // pojazd, który prowadzimy TDynamicObject *Controlled = NULL; // pojazd, który prowadzimy
@@ -205,7 +203,6 @@ TWorld::~TWorld()
TrainDelete(); TrainDelete();
// Ground.Free(); //Ra: usunięcie obiektów przed usunięciem dźwięków - sypie się // Ground.Free(); //Ra: usunięcie obiektów przed usunięciem dźwięków - sypie się
TSoundsManager::Free(); TSoundsManager::Free();
TModelsManager::Free();
} }
void TWorld::TrainDelete(TDynamicObject *d) void TWorld::TrainDelete(TDynamicObject *d)
@@ -290,22 +287,13 @@ bool TWorld::Init( GLFWwindow *Window ) {
"ShaXbee, Oli_EU, youBy, KURS90, Ra, hunter, szociu, Stele, Q, firleju and others\n" ); "ShaXbee, Oli_EU, youBy, KURS90, Ra, hunter, szociu, Stele, Q, firleju and others\n" );
UILayer.set_background( "logo" ); UILayer.set_background( "logo" );
/*
std::shared_ptr<ui_panel> initpanel = std::make_shared<ui_panel>(85, 600);
*/
TSoundsManager::Init( glfwGetWin32Window( window ) ); TSoundsManager::Init( glfwGetWin32Window( window ) );
WriteLog("Sound Init OK"); WriteLog("Sound Init OK");
TModelsManager::Init();
WriteLog("Models init OK");
/*
initpanel->text_lines.emplace_back( "Loading scenery / Wczytywanie scenerii:", float4( 0.0f, 0.0f, 0.0f, 1.0f ) );
initpanel->text_lines.emplace_back( Global::SceneryFile.substr(0, 40), float4( 0.0f, 0.0f, 0.0f, 1.0f ) );
UILayer.push_back( initpanel );
*/
glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii
UILayer.set_progress(0.01); UILayer.set_progress(0.01);
UILayer.set_progress( "Loading scenery / Wczytywanie scenerii" ); UILayer.set_progress( "Loading scenery / Wczytywanie scenerii" );
GfxRenderer.Render(); GfxRenderer.Render();
WriteLog( "Ground init" ); WriteLog( "Ground init" );
@@ -317,13 +305,8 @@ bool TWorld::Init( GLFWwindow *Window ) {
Environment.init(); Environment.init();
Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]); Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]);
/*
initpanel->text_lines.clear();
initpanel->text_lines.emplace_back( "Preparing train / Przygotowanie kabiny:", float4( 0.0f, 0.0f, 0.0f, 1.0f ) );
*/
UILayer.set_progress( "Preparing train / Przygotowanie kabiny" );
GfxRenderer.Render();
UILayer.set_progress( "Preparing train / Przygotowanie kabiny" );
WriteLog( "Player train init: " + Global::asHumanCtrlVehicle ); WriteLog( "Player train init: " + Global::asHumanCtrlVehicle );
TGroundNode *nPlayerTrain = NULL; TGroundNode *nPlayerTrain = NULL;
@@ -491,9 +474,8 @@ void TWorld::OnKeyDown(int cKey)
} }
else // również przeskakiwanie else // również przeskakiwanie
{ // Ra: to z tą kamerą (Camera.Pos i Global::pCameraPosition) jest trochę bez sensu { // Ra: to z tą kamerą (Camera.Pos i Global::pCameraPosition) jest trochę bez sensu
Global::SetCameraPosition( Ground.Silence( Global::pCameraPosition ); // wyciszenie wszystkiego z poprzedniej pozycji
Global::FreeCameraInit[i]); // nowa pozycja dla generowania obiektów Global::SetCameraPosition( Global::FreeCameraInit[i] ); // nowa pozycja dla generowania obiektów
Ground.Silence(Camera.Pos); // wyciszenie wszystkiego z poprzedniej pozycji
Camera.Init(Global::FreeCameraInit[i], Camera.Init(Global::FreeCameraInit[i],
Global::FreeCameraInitAngle[i]); // przestawienie Global::FreeCameraInitAngle[i]); // przestawienie
} }
@@ -634,18 +616,18 @@ void TWorld::OnKeyDown(int cKey)
break; break;
} }
case GLFW_KEY_F8: { case GLFW_KEY_F8: {
#ifdef EU07_USE_DEBUG_SHADOWMAP if( Global::ctrlState
if( Global::iTextMode == cKey ) { ++Global::iScreenMode[ cKey - GLFW_KEY_F1 ]; } && Global::shiftState ) {
if( Global::iScreenMode[ cKey - GLFW_KEY_F1 ] > 1 ) { DebugCameraFlag = !DebugCameraFlag; // taka opcjonalna funkcja, może się czasem przydać
Global::iScreenMode[ cKey - GLFW_KEY_F1 ] = 0; }
else {
Global::iTextMode = cKey;
} }
#endif
Global::iTextMode = cKey;
break; break;
} }
case GLFW_KEY_F9: { case GLFW_KEY_F9: {
Global::iTextMode = cKey; Global::iTextMode = cKey;
// wersja, typ wyświetlania, błędy OpenGL // wersja
break; break;
} }
case GLFW_KEY_F10: { case GLFW_KEY_F10: {
@@ -1058,17 +1040,17 @@ bool TWorld::Update()
// NOTE: experimentally changing this to prevent the desync. // NOTE: experimentally changing this to prevent the desync.
// TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps // TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps
Ground.Update(dt / updatecount, updatecount); // tu zrobić tylko coklatkową aktualizację przesunięć Ground.Update(dt / updatecount, updatecount); // tu zrobić tylko coklatkową aktualizację przesunięć
/*
if (DebugModeFlag) // yB dodał przyspieszacz fizyki
if (Global::bActive) // nie przyspieszać, gdy jedzie w tle :) if( (true == DebugModeFlag)
if( Console::Pressed( GLFW_KEY_ESCAPE ) ) { && (true == Global::bActive) // nie przyspieszać, gdy jedzie w tle :)
// yB dodał przyspieszacz fizyki && ( glfwGetKey( window, GLFW_KEY_PAUSE ) == GLFW_PRESS ) ) {
Ground.Update(dt, n);
Ground.Update(dt, n); Ground.Update( dt, updatecount );
Ground.Update(dt, n); Ground.Update( dt, updatecount );
Ground.Update(dt, n); // 5 razy Ground.Update( dt, updatecount );
} Ground.Update( dt, updatecount ); // 5 razy
*/ }
// secondary fixed step simulation time routines // secondary fixed step simulation time routines
while( m_secondaryupdateaccumulator >= m_secondaryupdaterate ) { while( m_secondaryupdateaccumulator >= m_secondaryupdaterate ) {
@@ -1083,8 +1065,9 @@ bool TWorld::Update()
} }
// fixed step part of the camera update // fixed step part of the camera update
if( (Train != nullptr) if( ( Train != nullptr )
&& (Camera.Type == tp_Follow )) { && ( Camera.Type == tp_Follow )
&& ( false == DebugCameraFlag ) ) {
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery // jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
Train->UpdateMechPosition( m_secondaryupdaterate ); Train->UpdateMechPosition( m_secondaryupdaterate );
} }
@@ -1121,11 +1104,16 @@ bool TWorld::Update()
while( fTime50Hz >= 1.0 / 50.0 ) { while( fTime50Hz >= 1.0 / 50.0 ) {
Console::Update(); // to i tak trzeba wywoływać Console::Update(); // to i tak trzeba wywoływać
Update_UI(); Update_UI();
// decelerate camera
Camera.Velocity *= 0.65; Camera.Velocity *= 0.65;
if( std::abs( Camera.Velocity.x ) < 0.01 ) { Camera.Velocity.x = 0.0; } if( std::abs( Camera.Velocity.x ) < 0.01 ) { Camera.Velocity.x = 0.0; }
if( std::abs( Camera.Velocity.y ) < 0.01 ) { Camera.Velocity.y = 0.0; } if( std::abs( Camera.Velocity.y ) < 0.01 ) { Camera.Velocity.y = 0.0; }
if( std::abs( Camera.Velocity.z ) < 0.01 ) { Camera.Velocity.z = 0.0; } if( std::abs( Camera.Velocity.z ) < 0.01 ) { Camera.Velocity.z = 0.0; }
// decelerate debug camera too
DebugCamera.Velocity *= 0.65;
if( std::abs( DebugCamera.Velocity.x ) < 0.01 ) { DebugCamera.Velocity.x = 0.0; }
if( std::abs( DebugCamera.Velocity.y ) < 0.01 ) { DebugCamera.Velocity.y = 0.0; }
if( std::abs( DebugCamera.Velocity.z ) < 0.01 ) { DebugCamera.Velocity.z = 0.0; }
fTime50Hz -= 1.0 / 50.0; fTime50Hz -= 1.0 / 50.0;
} }
@@ -1144,25 +1132,25 @@ bool TWorld::Update()
void void
TWorld::Update_Camera( double const Deltatime ) { TWorld::Update_Camera( double const Deltatime ) {
// Console::Update(); //tu jest zależne od FPS, co nie jest korzystne
if( false == Global::ControlPicking ) { if( false == Global::ControlPicking ) {
if( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_LEFT ) == GLFW_PRESS ) { if( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_LEFT ) == GLFW_PRESS ) {
Camera.Reset(); // likwidacja obrotów - patrzy horyzontalnie na południe Camera.Reset(); // likwidacja obrotów - patrzy horyzontalnie na południe
// if (!FreeFlyModeFlag) //jeśli wewnątrz - patrzymy do tyłu if( Controlled && LengthSquared3( Controlled->GetPosition() - Camera.Pos ) < ( 1500 * 1500 ) ) {
// Camera.LookAt=Train->pMechPosition-Normalize(Train->GetDirection())*10; // gdy bliżej niż 1.5km
if( Controlled && LengthSquared3( Controlled->GetPosition() - Camera.Pos ) < ( 1500 * 1500 ) ) // gdy bliżej niż 1.5km
Camera.LookAt = Controlled->GetPosition(); Camera.LookAt = Controlled->GetPosition();
}
else { else {
TDynamicObject *d = TDynamicObject *d =
Ground.DynamicNearest( Camera.Pos, 300 ); // szukaj w promieniu 300m Ground.DynamicNearest( Camera.Pos, 300 ); // szukaj w promieniu 300m
if( !d ) if( !d )
d = Ground.DynamicNearest( Camera.Pos, d = Ground.DynamicNearest( Camera.Pos, 1000 ); // dalej szukanie, jesli bliżej nie ma
1000 ); // dalej szukanie, jesli bliżej nie ma if( d && pDynamicNearest ) {
if( d && pDynamicNearest ) // jeśli jakiś jest znaleziony wcześniej // jeśli jakiś jest znaleziony wcześniej
if( 100.0 * LengthSquared3( d->GetPosition() - Camera.Pos ) > if( 100.0 * LengthSquared3( d->GetPosition() - Camera.Pos ) > LengthSquared3( pDynamicNearest->GetPosition() - Camera.Pos ) ) {
LengthSquared3( pDynamicNearest->GetPosition() - Camera.Pos ) )
d = pDynamicNearest; // jeśli najbliższy nie jest 10 razy bliżej niż d = pDynamicNearest; // jeśli najbliższy nie jest 10 razy bliżej niż
}
}
// poprzedni najbliższy, zostaje poprzedni // poprzedni najbliższy, zostaje poprzedni
if( d ) if( d )
pDynamicNearest = d; // zmiana na nowy, jeśli coś znaleziony niepusty pDynamicNearest = d; // zmiana na nowy, jeśli coś znaleziony niepusty
@@ -1172,7 +1160,7 @@ TWorld::Update_Camera( double const Deltatime ) {
if( FreeFlyModeFlag ) if( FreeFlyModeFlag )
Camera.RaLook(); // jednorazowe przestawienie kamery Camera.RaLook(); // jednorazowe przestawienie kamery
} }
else if( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_RIGHT ) == GLFW_PRESS ) { //||Console::Pressed(VK_F4)) else if( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_RIGHT ) == GLFW_PRESS ) {
FollowView( false ); // bez wyciszania dźwięków FollowView( false ); // bez wyciszania dźwięków
} }
else if( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_MIDDLE ) == GLFW_PRESS ) { else if( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_MIDDLE ) == GLFW_PRESS ) {
@@ -1186,15 +1174,12 @@ TWorld::Update_Camera( double const Deltatime ) {
} }
} }
Camera.Update(); // uwzględnienie ruchu wywołanego klawiszami if( DebugCameraFlag ) { DebugCamera.Update(); }
/* else { Camera.Update(); } // uwzględnienie ruchu wywołanego klawiszami
if( Camera.Type == tp_Follow ) {
if( Train ) { // jeśli jazda w kabinie, przeliczyć trzeba parametry kamery if( ( Train != nullptr )
Train->UpdateMechPosition( Deltatime / && ( Camera.Type == tp_Follow )
Global::fTimeSpeed ); // ograniczyć telepanie po przyspieszeniu && ( false == DebugCameraFlag ) ) {
*/
if( (Train != nullptr)
&& (Camera.Type == tp_Follow )) {
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery // jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
vector3 tempangle = Controlled->VectorFront() * ( Controlled->MoverParameters->ActiveCab == -1 ? -1 : 1 ); vector3 tempangle = Controlled->VectorFront() * ( Controlled->MoverParameters->ActiveCab == -1 ? -1 : 1 );
double modelrotate = atan2( -tempangle.x, tempangle.z ); double modelrotate = atan2( -tempangle.x, tempangle.z );
@@ -1256,6 +1241,9 @@ TWorld::Update_Camera( double const Deltatime ) {
else { // kamera nieruchoma else { // kamera nieruchoma
Global::SetCameraRotation( Camera.Yaw - M_PI ); Global::SetCameraRotation( Camera.Yaw - M_PI );
} }
// all done, update camera position to the new value
Global::pCameraPosition = Camera.Pos;
Global::DebugCameraPosition = DebugCamera.Pos;
} }
void TWorld::Update_Environment() { void TWorld::Update_Environment() {
@@ -1609,8 +1597,9 @@ TWorld::Update_UI() {
uitextline1 = uitextline1 =
"FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 ) "FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 )
+ ", Draw range x " + to_string( Global::fDistanceFactor, 1 ) + ", Draw range x " + to_string( Global::fDistanceFactor, 1 )
+ "; sectors: " + std::to_string( GfxRenderer.m_drawcount ) // + "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
+ ", FPS: " + to_string( Timer::GetFPS(), 2 ); // + ", FPS: " + to_string( Timer::GetFPS(), 2 );
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer.Framerate())) );
if( Global::iSlowMotion ) { if( Global::iSlowMotion ) {
uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")"; uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
} }
@@ -2229,10 +2218,12 @@ world_environment::update() {
m_sun.update(); m_sun.update();
m_moon.update(); m_moon.update();
// ...determine source of key light and adjust global state accordingly... // ...determine source of key light and adjust global state accordingly...
auto const sunlightlevel = m_sun.getIntensity(); // diffuse (sun) intensity goes down after twilight, and reaches minimum 18 degrees below horizon
float twilightfactor = clamp( -m_sun.getAngle(), 0.0f, 18.0f ) / 18.0f;
// NOTE: sun light receives extra padding to prevent moon from kicking in too soon
auto const sunlightlevel = m_sun.getIntensity() + 0.05f * ( 1.f - twilightfactor );
auto const moonlightlevel = m_moon.getIntensity() * 0.65f; // scaled down by arbitrary factor, it's pretty bright otherwise auto const moonlightlevel = m_moon.getIntensity() * 0.65f; // scaled down by arbitrary factor, it's pretty bright otherwise
float keylightintensity; float keylightintensity;
float twilightfactor;
glm::vec3 keylightcolor; glm::vec3 keylightcolor;
if( moonlightlevel > sunlightlevel ) { if( moonlightlevel > sunlightlevel ) {
// rare situations when the moon is brighter than the sun, typically at night // rare situations when the moon is brighter than the sun, typically at night
@@ -2250,8 +2241,7 @@ world_environment::update() {
Global::DayLight.set_position( m_sun.getPosition() ); Global::DayLight.set_position( m_sun.getPosition() );
Global::DayLight.direction = -1.0f * m_sun.getDirection(); Global::DayLight.direction = -1.0f * m_sun.getDirection();
keylightintensity = sunlightlevel; keylightintensity = sunlightlevel;
// diffuse (sun) intensity goes down after twilight, and reaches minimum 18 degrees below horizon // include 'golden hour' effect in twilight lighting
twilightfactor = clamp( -Global::SunAngle, 0.0f, 18.0f ) / 18.0f;
float const duskfactor = 1.0f - clamp( Global::SunAngle, 0.0f, 18.0f ) / 18.0f; float const duskfactor = 1.0f - clamp( Global::SunAngle, 0.0f, 18.0f ) / 18.0f;
keylightcolor = interpolate( keylightcolor = interpolate(
glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ), glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ),

View File

@@ -118,6 +118,7 @@ private:
void ResourceSweep(); void ResourceSweep();
TCamera Camera; TCamera Camera;
TCamera DebugCamera;
TGround Ground; TGround Ground;
world_environment Environment; world_environment Environment;
TTrain *Train; TTrain *Train;

View File

@@ -22,8 +22,8 @@ cFrustum::calculate() {
void void
cFrustum::calculate( glm::mat4 const &Projection, glm::mat4 const &Modelview ) { cFrustum::calculate( glm::mat4 const &Projection, glm::mat4 const &Modelview ) {
float const *proj = &Projection[ 0 ][ 0 ]; float const *proj = glm::value_ptr( Projection );
float const *modl = &Modelview[ 0 ][ 0 ]; float const *modl = glm::value_ptr( Modelview );
float clip[ 16 ]; float clip[ 16 ];
// multiply the matrices to retrieve clipping planes // multiply the matrices to retrieve clipping planes

View File

@@ -12,6 +12,12 @@ http://mozilla.org/MPL/2.0/.
#include "float3d.h" #include "float3d.h"
#include "dumb3d.h" #include "dumb3d.h"
std::vector<glm::vec4> const ndcfrustumshapepoints {
{ -1, -1, -1, 1 },{ 1, -1, -1, 1 },{ 1, 1, -1, 1 },{ -1, 1, -1, 1 }, // z-near
{ -1, -1, 1, 1 },{ 1, -1, 1, 1 },{ 1, 1, 1, 1 },{ -1, 1, 1, 1 } }; // z-far
std::vector<std::size_t> const frustumshapepoinstorder { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 };
// generic frustum class. used to determine if objects are inside current view area // generic frustum class. used to determine if objects are inside current view area
class cFrustum { class cFrustum {
@@ -62,7 +68,7 @@ public:
bool bool
cube_inside( float const X, float const Y, float const Z, float const Size ) const; cube_inside( float const X, float const Y, float const Z, float const Size ) const;
protected: private:
// types: // types:
// planes of the frustum // planes of the frustum
enum side { side_RIGHT = 0, side_LEFT = 1, side_BOTTOM = 2, side_TOP = 3, side_BACK = 4, side_FRONT = 5 }; enum side { side_RIGHT = 0, side_LEFT = 1, side_BOTTOM = 2, side_TOP = 3, side_BACK = 4, side_FRONT = 5 };
@@ -74,5 +80,5 @@ protected:
normalize_plane( cFrustum::side const Side ); // normalizes a plane (A side) from the frustum normalize_plane( cFrustum::side const Side ); // normalizes a plane (A side) from the frustum
// members: // members:
float m_frustum[6][4]; // holds the A B C and D values (normal & distance) for each side of the frustum. float m_frustum[6][4]; // holds the A B C and D values (normal & distance) for each side of the frustum.
}; };

View File

@@ -60,10 +60,10 @@ light_array::update() {
if( ( true == light.owner->MoverParameters->Battery ) || ( true == light.owner->MoverParameters->ConverterFlag ) ) { if( ( true == light.owner->MoverParameters->Battery ) || ( true == light.owner->MoverParameters->ConverterFlag ) ) {
// with power on, the intensity depends on the state of activated switches // with power on, the intensity depends on the state of activated switches
auto const &lightbits = light.owner->iLights[ light.index ]; auto const &lightbits = light.owner->iLights[ light.index ];
light.count = 0 + light.count = 0
( ( lightbits & 1 ) ? 1 : 0 ) + + ( ( lightbits & TMoverParameters::light::headlight_left ) ? 1 : 0 )
( ( lightbits & 4 ) ? 1 : 0 ) + + ( ( lightbits & TMoverParameters::light::headlight_right ) ? 1 : 0 )
( ( lightbits & 16 ) ? 1 : 0 ); + ( ( lightbits & TMoverParameters::light::headlight_upper ) ? 1 : 0 );
if( light.count > 0 ) { if( light.count > 0 ) {
// TODO: intensity can be affected further by dim switch or other factors // TODO: intensity can be affected further by dim switch or other factors

View File

@@ -19,9 +19,9 @@ public:
TDynamicObject const *owner; // the object in world which 'carries' the light TDynamicObject const *owner; // the object in world which 'carries' the light
int index{ -1 }; // 0: front lights, 1: rear lights int index{ -1 }; // 0: front lights, 1: rear lights
Math3D::vector3 position; // position of the light in 3d scene glm::dvec3 position; // position of the light in 3d scene
glm::vec3 direction; // direction of the light in 3d scene glm::vec3 direction; // direction of the light in 3d scene
float3 color{ 255.0f / 255.0f, 241.0f / 255.0f, 224.0f / 255.0f }; // color of the light, default is halogen light glm::vec3 color{ 255.0f / 255.0f, 241.0f / 255.0f, 224.0f / 255.0f }; // color of the light, default is halogen light
float intensity{ 0.0f }; // (combined) intensity of the light(s) float intensity{ 0.0f }; // (combined) intensity of the light(s)
int count{ 0 }; // number (or pattern) of active light(s) int count{ 0 }; // number (or pattern) of active light(s)
}; };

View File

@@ -63,9 +63,6 @@
<ClCompile Include="EvLaunch.cpp"> <ClCompile Include="EvLaunch.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="FadeSound.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Float3d.cpp"> <ClCompile Include="Float3d.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@@ -120,9 +117,6 @@
<ClCompile Include="Texture.cpp"> <ClCompile Include="Texture.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="TextureDDS.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Timer.cpp"> <ClCompile Include="Timer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@@ -344,9 +338,6 @@
<ClInclude Include="Names.h"> <ClInclude Include="Names.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="FadeSound.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Sound.h"> <ClInclude Include="Sound.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@@ -377,9 +368,6 @@
<ClInclude Include="Timer.h"> <ClInclude Include="Timer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="TextureDDS.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ResourceManager.h"> <ClInclude Include="ResourceManager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View File

@@ -36,9 +36,9 @@ void
cMoon::update() { cMoon::update() {
move(); move();
glm::vec3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); glm::vec3 position( 0.f, 0.f, -2000.f * Global::fDistanceFactor );
position = glm::rotateX( position, (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); position = glm::rotateX( position, glm::radians<float>( m_body.elevref ) );
position = glm::rotateY( position, (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); position = glm::rotateY( position, glm::radians<float>( -m_body.hrang ) );
m_position = position; m_position = position;
} }
@@ -55,7 +55,7 @@ cMoon::render() {
glEnd(); glEnd();
glPushMatrix(); glPushMatrix();
glTranslatef( position.x, position.y, position.z ); glTranslatef( position.x, position.y, position.z );
gluSphere( moonsphere, /* (float)( Global::ScreenHeight / Global::FieldOfView ) * 0.5 * */ ( m_body.distance / 60.2666 ) * 9.037461, 12, 12 ); gluSphere( moonsphere, /* (float)( Global::iWindowHeight / Global::FieldOfView ) * 0.5 * */ ( m_body.distance / 60.2666 ) * 9.037461, 12, 12 );
glPopMatrix(); glPopMatrix();
} }

View File

@@ -168,7 +168,7 @@ mouse_input::poll() {
auto updaterate { m_updaterate }; auto updaterate { m_updaterate };
if( m_varyingpollrate ) { if( m_varyingpollrate ) {
updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_commandstartcursor ) / std::max( 1, Global::ScreenHeight ) ); updaterate /= std::max( 0.15, 2.0 * glm::length( m_cursorposition - m_commandstartcursor ) / std::max( 1, Global::iWindowHeight ) );
} }
if( m_updateaccumulator < updaterate ) { if( m_updateaccumulator < updaterate ) {

View File

@@ -25,8 +25,8 @@ struct basic_vertex {
glm::vec2 texture; // uv space glm::vec2 texture; // uv space
basic_vertex() = default; basic_vertex() = default;
basic_vertex( glm::vec3 const&Position, glm::vec3 const &Normal, glm::vec2 const &Texture ) : basic_vertex( glm::vec3 const &Position, glm::vec3 const &Normal, glm::vec2 const &Texture ) :
position( Position ), normal( Normal ), texture( Texture ) position( Position ), normal( Normal ), texture( Texture )
{} {}
void serialize( std::ostream& ) const; void serialize( std::ostream& ) const;
void deserialize( std::istream& ); void deserialize( std::istream& );

View File

@@ -31,17 +31,23 @@ public:
// methods: // methods:
glm::mat4 const & glm::mat4 const &
data() const { return m_stack.top(); } data() const {
return m_stack.top(); }
void void
push_matrix() { m_stack.emplace(m_stack.top()); } push_matrix() {
m_stack.emplace( m_stack.top() ); }
void void
pop_matrix() { pop_matrix() {
m_stack.pop(); m_stack.pop();
if( m_stack.empty() ) { m_stack.emplace(1.0f); } if( m_stack.empty() ) { m_stack.emplace( 1.f ); }
upload(); } upload(); }
void void
load_identity() { load_identity() {
m_stack.top() = glm::mat4( 1.0f ); m_stack.top() = glm::mat4( 1.f );
upload(); }
void
load_matrix( glm::mat4 const &Matrix ) {
m_stack.top() = Matrix;
upload(); } upload(); }
void void
rotate( float const Angle, glm::vec3 const &Axis ) { rotate( float const Angle, glm::vec3 const &Axis ) {
@@ -113,6 +119,11 @@ public:
pop_matrix() { m_stacks[ m_mode ].pop_matrix(); } pop_matrix() { m_stacks[ m_mode ].pop_matrix(); }
void void
load_identity() { m_stacks[ m_mode ].load_identity(); } load_identity() { m_stacks[ m_mode ].load_identity(); }
void
load_matrix( glm::mat4 const &Matrix ) { m_stacks[ m_mode ].load_matrix( Matrix ); }
template <typename Type_>
void
load_matrix( Type_ const *Matrix ) { load_matrix( glm::make_mat4( Matrix ) ); }
template <typename Type_> template <typename Type_>
void void
rotate( Type_ const Angle, Type_ const X, Type_ const Y, Type_ const Z ) { rotate( Type_ const Angle, Type_ const X, Type_ const Y, Type_ const Z ) {
@@ -184,6 +195,8 @@ extern opengl_matrices OpenGLMatrices;
#define glPushMatrix OpenGLMatrices.push_matrix #define glPushMatrix OpenGLMatrices.push_matrix
#define glPopMatrix OpenGLMatrices.pop_matrix #define glPopMatrix OpenGLMatrices.pop_matrix
#define glLoadIdentity OpenGLMatrices.load_identity #define glLoadIdentity OpenGLMatrices.load_identity
#define glLoadMatrixf OpenGLMatrices.load_matrix
#define glLoadMatrixd OpenGLMatrices.load_matrix
#define glRotated OpenGLMatrices.rotate #define glRotated OpenGLMatrices.rotate
#define glRotatef OpenGLMatrices.rotate #define glRotatef OpenGLMatrices.rotate
#define glTranslated OpenGLMatrices.translate #define glTranslated OpenGLMatrices.translate

View File

@@ -72,6 +72,42 @@ cParser::~cParser()
mComments.clear(); mComments.clear();
} }
template<>
cParser&
cParser::operator>>( std::string &Right ) {
if( true == this->tokens.empty() ) { return *this; }
Right = this->tokens.front();
this->tokens.pop_front();
return *this;
}
template<>
cParser&
cParser::operator>>( bool &Right ) {
if( true == this->tokens.empty() ) { return *this; }
Right = ( ( this->tokens.front() == "true" )
|| ( this->tokens.front() == "yes" )
|| ( this->tokens.front() == "1" ) );
this->tokens.pop_front();
return *this;
}
template <>
bool
cParser::getToken<bool>( bool const ToLower, const char *Break ) {
auto const token = getToken<std::string>( true, Break );
return ( ( token == "true" )
|| ( token == "yes" )
|| ( token == "1" ) );
}
// methods // methods
bool cParser::getTokens(unsigned int Count, bool ToLower, const char *Break) bool cParser::getTokens(unsigned int Count, bool ToLower, const char *Break)
{ {

View File

@@ -35,12 +35,6 @@ class cParser //: public std::stringstream
template <typename Type_> template <typename Type_>
cParser & cParser &
operator>>( Type_ &Right ); operator>>( Type_ &Right );
template <>
cParser &
operator>>( std::string &Right );
template <>
cParser &
operator>>( bool &Right );
template <typename Output_> template <typename Output_>
Output_ Output_
getToken( bool const ToLower = true, const char *Break = "\n\r\t ;" ) { getToken( bool const ToLower = true, const char *Break = "\n\r\t ;" ) {
@@ -48,41 +42,34 @@ class cParser //: public std::stringstream
Output_ output; Output_ output;
*this >> output; *this >> output;
return output; }; return output; };
template <> inline
bool void
getToken<bool>( bool const ToLower, const char *Break ) { ignoreToken() {
auto const token = getToken<std::string>( true, Break ); readToken(); };
return ( ( token == "true" ) inline
|| ( token == "yes" ) void
|| ( token == "1" ) ); } ignoreTokens(int count) {
inline void ignoreToken() for( int i = 0; i < count; ++i ) {
{ readToken(); } };
readToken(); inline
}; bool
inline void ignoreTokens(int count) expectToken( std::string const &Value ) {
{ return readToken() == Value; };
for (int i = 0; i < count; i++) bool
readToken(); eof() {
}; return mStream->eof(); };
inline bool expectToken(std::string const &value) bool
{ ok() {
return readToken() == value; return !mStream->fail(); };
}; bool
bool eof() getTokens( unsigned int Count = 1, bool ToLower = true, char const *Break = "\n\r\t ;" );
{
return mStream->eof();
};
bool ok()
{
return !mStream->fail();
};
bool getTokens(unsigned int Count = 1, bool ToLower = true, char const *Break = "\n\r\t ;");
// returns next incoming token, if any, without removing it from the set // returns next incoming token, if any, without removing it from the set
std::string peek() const { std::string
return ( peek() const {
false == tokens.empty() ? return (
tokens.front() : false == tokens.empty() ?
"" ); } tokens.front() :
"" ); }
// returns percentage of file processed so far // returns percentage of file processed so far
int getProgress() const; int getProgress() const;
int getFullProgress() const; int getFullProgress() const;
@@ -129,26 +116,12 @@ cParser::operator>>( Type_ &Right ) {
template<> template<>
cParser& cParser&
cParser::operator>>( std::string &Right ) { cParser::operator>>( std::string &Right );
if( true == this->tokens.empty() ) { return *this; }
Right = this->tokens.front();
this->tokens.pop_front();
return *this;
}
template<> template<>
cParser& cParser&
cParser::operator>>( bool &Right ) { cParser::operator>>( bool &Right );
if( true == this->tokens.empty() ) { return *this; } template<>
bool
Right = ( ( this->tokens.front() == "true" ) cParser::getToken<bool>( bool const ToLower, const char *Break );
|| ( this->tokens.front() == "yes" )
|| ( this->tokens.front() == "1" ) );
this->tokens.pop_front();
return *this;
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,15 +18,19 @@ http://mozilla.org/MPL/2.0/.
#include "world.h" #include "world.h"
#include "memcell.h" #include "memcell.h"
#define EU07_USE_PICKING_FRAMEBUFFER
//#define EU07_USE_DEBUG_SHADOWMAP
//#define EU07_USE_DEBUG_CAMERA
struct opengl_light { struct opengl_light {
GLuint id{ (GLuint)-1 }; GLuint id{ (GLuint)-1 };
glm::vec3 direction; glm::vec3 direction;
glm::vec4 glm::vec4
position { 0.0f, 0.0f, 0.0f, 1.0f }, // 4th parameter specifies directional(0) or omni-directional(1) light source position { 0.f, 0.f, 0.f, 1.f }, // 4th parameter specifies directional(0) or omni-directional(1) light source
ambient { 0.0f, 0.0f, 0.0f, 1.0f }, ambient { 0.f, 0.f, 0.f, 1.f },
diffuse { 1.0f, 1.0f, 1.0f, 1.0f }, diffuse { 1.f, 1.f, 1.f, 1.f },
specular { 1.0f, 1.0f, 1.0f, 1.0f }; specular { 1.f, 1.f, 1.f, 1.f };
inline inline
void apply_intensity( float const Factor = 1.0f ) { void apply_intensity( float const Factor = 1.0f ) {
@@ -51,7 +55,7 @@ struct opengl_light {
void apply_angle() { void apply_angle() {
glLightfv( id, GL_POSITION, glm::value_ptr(position) ); glLightfv( id, GL_POSITION, glm::value_ptr(position) );
if( position.w == 1.0f ) { if( position.w == 1.f ) {
glLightfv( id, GL_SPOT_DIRECTION, glm::value_ptr(direction) ); glLightfv( id, GL_SPOT_DIRECTION, glm::value_ptr(direction) );
} }
} }
@@ -83,10 +87,9 @@ public:
// methods: // methods:
inline inline
void void
update_frustum() { m_frustum.calculate(); } update_frustum() { update_frustum( m_projection, m_modelview ); }
inline
void void
update_frustum(glm::mat4 const &Projection, glm::mat4 const &Modelview) { m_frustum.calculate(Projection, Modelview); } update_frustum( glm::mat4 const &Projection, glm::mat4 const &Modelview );
bool bool
visible( bounding_area const &Area ) const; visible( bounding_area const &Area ) const;
bool bool
@@ -97,11 +100,44 @@ public:
inline inline
glm::dvec3 & glm::dvec3 &
position() { return m_position; } position() { return m_position; }
inline
glm::mat4 const &
projection() const { return m_projection; }
inline
glm::mat4 &
projection() { return m_projection; }
inline
glm::mat4 const &
modelview() const { return m_modelview; }
inline
glm::mat4 &
modelview() { return m_modelview; }
inline
std::vector<glm::vec4> &
frustum_points() { return m_frustumpoints; }
// transforms provided set of clip space points to world space
template <class Iterator_>
void
transform_to_world( Iterator_ First, Iterator_ Last ) const {
std::for_each(
First, Last,
[this]( glm::vec4 &point ) {
// transform each point using the cached matrix...
point = this->m_inversetransformation * point;
// ...and scale by transformed w
point = glm::vec4{ glm::vec3{ point } / point.w, 1.f }; } ); }
// debug helper, draws shape of frustum in world space
void
draw( glm::vec3 const &Offset ) const;
private: private:
// members: // members:
cFrustum m_frustum; cFrustum m_frustum;
std::vector<glm::vec4> m_frustumpoints; // visualization helper; corners of defined frustum, in world space
glm::dvec3 m_position; glm::dvec3 m_position;
glm::mat4 m_projection;
glm::mat4 m_modelview;
glm::mat4 m_inversetransformation; // cached transformation to world space
}; };
// bare-bones render controller, in lack of anything better yet // bare-bones render controller, in lack of anything better yet
@@ -119,6 +155,9 @@ public:
// main draw call. returns false on error // main draw call. returns false on error
bool bool
Render(); Render();
inline
float
Framerate() { return m_framerate; }
// geometry methods // geometry methods
// NOTE: hands-on geometry management is exposed as a temporary measure; ultimately all visualization data should be generated/handled automatically by the renderer itself // NOTE: hands-on geometry management is exposed as a temporary measure; ultimately all visualization data should be generated/handled automatically by the renderer itself
// creates a new geometry bank. returns: handle to the bank or NULL // creates a new geometry bank. returns: handle to the bank or NULL
@@ -159,7 +198,7 @@ public:
TGroundNode const * TGroundNode const *
Update_Pick_Node(); Update_Pick_Node();
// debug performance string // debug performance string
std::string std::string const &
Info() const; Info() const;
// members // members
@@ -179,10 +218,10 @@ private:
typedef std::pair< double, TSubRect * > distancesubcell_pair; typedef std::pair< double, TSubRect * > distancesubcell_pair;
struct renderpass_config { struct renderpass_config {
opengl_camera camera; opengl_camera camera;
rendermode draw_mode { rendermode::color }; rendermode draw_mode { rendermode::none };
float draw_range { 0.0f }; float draw_range { 0.0f };
std::vector<distancesubcell_pair> draw_queue; // list of subcells to be drawn in current render pass
}; };
typedef std::vector<opengl_light> opengllight_array; typedef std::vector<opengl_light> opengllight_array;
@@ -193,24 +232,10 @@ private:
// runs jobs needed to generate graphics for specified render pass // runs jobs needed to generate graphics for specified render pass
void void
Render_pass( rendermode const Mode ); Render_pass( rendermode const Mode );
// configures projection matrix for the current render pass
void void
setup_projection(); setup_pass( renderpass_config &Config, rendermode const Mode, float const Znear = 0.f, float const Zfar = 1.f, bool const Ignoredebug = false );
void void
setup_projection_world(); setup_matrices();
void
setup_projection_light_ortho();
void
setup_projection_light_perspective();
// configures camera for the current render pass
void
setup_camera();
void
setup_camera_world( glm::dmat4 &Viewmatrix );
void
setup_camera_light_ortho( glm::dmat4 &Viewmatrix );
void
setup_camera_light_perspective( glm::dmat4 &Viewmatrix );
void void
setup_drawing( bool const Alpha = false ); setup_drawing( bool const Alpha = false );
void void
@@ -218,7 +243,7 @@ private:
void void
setup_shadow_color( glm::vec4 const &Shadowcolor ); setup_shadow_color( glm::vec4 const &Shadowcolor );
void void
toggle_units( bool const Diffuse, bool const Shadows, bool const Reflections ); switch_units( bool const Diffuse, bool const Shadows, bool const Reflections );
bool bool
Render( world_environment *Environment ); Render( world_environment *Environment );
bool bool
@@ -258,53 +283,67 @@ private:
void void
Render_Alpha( TSubModel *Submodel ); Render_Alpha( TSubModel *Submodel );
void void
Update_Lights( light_array const &Lights ); Update_Lights( light_array &Lights );
glm::vec3 glm::vec3
pick_color( std::size_t const Index ); pick_color( std::size_t const Index );
std::size_t std::size_t
pick_index( glm::ivec3 const &Color ); pick_index( glm::ivec3 const &Color );
// members // members
GLFWwindow *m_window { nullptr };
geometrybank_manager m_geometry; geometrybank_manager m_geometry;
texture_manager m_textures; texture_manager m_textures;
opengllight_array m_lights; opengllight_array m_lights;
GLFWwindow *m_window { nullptr };
#ifdef EU07_USE_PICKING_FRAMEBUFFER
GLuint m_pickframebuffer { 0 }; // TODO: refactor pick framebuffer stuff into an object
GLuint m_picktexture { 0 };
GLuint m_pickdepthbuffer { 0 };
int m_pickbuffersize { 1024 }; // size of (square) textures bound with the pick framebuffer
#endif
GLuint m_shadowframebuffer { 0 };
GLuint m_shadowtexture { 0 };
int m_shadowbuffersize { 4096 };
glm::mat4 m_shadowtexturematrix;
glm::vec4 m_shadowcolor{ 0.5f, 0.5f, 0.5f, 1.f };
GLUquadricObj *m_quadric { nullptr }; // helper object for drawing debug mode scene elements
int m_shadowtextureunit { GL_TEXTURE1 };
int m_helpertextureunit { GL_TEXTURE0 };
int m_diffusetextureunit { GL_TEXTURE2 };
geometry_handle m_billboardgeometry { 0, 0 }; geometry_handle m_billboardgeometry { NULL, NULL };
texture_handle m_glaretexture { -1 }; texture_handle m_glaretexture { -1 };
texture_handle m_suntexture { -1 }; texture_handle m_suntexture { -1 };
texture_handle m_moontexture { -1 }; texture_handle m_moontexture { -1 };
texture_handle m_reflectiontexture { -1 }; texture_handle m_reflectiontexture { -1 };
GLUquadricObj *m_quadric { nullptr }; // helper object for drawing debug mode scene elements
float m_drawtime { 1000.0f / 30.0f * 20.0f }; // start with presumed 'neutral' average of 30 fps bool m_framebuffersupport { false };
#ifdef EU07_USE_PICKING_FRAMEBUFFER
GLuint m_pickframebuffer { NULL }; // TODO: refactor pick framebuffer stuff into an object
GLuint m_picktexture { NULL };
GLuint m_pickdepthbuffer { NULL };
#endif
int m_shadowbuffersize { 4096 };
GLuint m_shadowframebuffer { NULL };
GLuint m_shadowtexture { NULL };
#ifdef EU07_USE_DEBUG_SHADOWMAP
GLuint m_shadowdebugtexture{ NULL };
#endif
glm::mat4 m_shadowtexturematrix; // conversion from camera-centric world space to light-centric clip space
int m_shadowtextureunit { GL_TEXTURE1 };
int m_helpertextureunit { GL_TEXTURE0 };
int m_diffusetextureunit { GL_TEXTURE2 };
float m_drawtime { 1000.f / 30.f * 20.f }; // start with presumed 'neutral' average of 30 fps
std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame
float m_framerate;
float m_drawtimecolorpass { 1000.f / 30.f * 20.f };
float m_drawtimeshadowpass { 0.f };
double m_updateaccumulator { 0.0 }; double m_updateaccumulator { 0.0 };
std::string m_debuginfo; std::string m_debuginfo;
glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f }; glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f };
float m_specularopaquescalefactor { 1.0f }; glm::vec4 m_shadowcolor { 0.5f, 0.5f, 0.5f, 1.f };
float m_speculartranslucentscalefactor { 1.0f }; float m_specularopaquescalefactor { 1.f };
float m_speculartranslucentscalefactor { 1.f };
bool m_renderspecular{ false }; // controls whether to include specular component in the calculations
bool m_framebuffersupport { false };
renderpass_config m_renderpass; renderpass_config m_renderpass;
bool m_renderspecular { false }; // controls whether to include specular component in the calculations std::vector<distancesubcell_pair> m_drawqueue; // list of subcells to be drawn in current render pass
std::vector<TGroundNode const *> m_picksceneryitems; std::vector<TGroundNode const *> m_picksceneryitems;
std::vector<TSubModel const *> m_pickcontrolsitems; std::vector<TSubModel const *> m_pickcontrolsitems;
TSubModel const *m_pickcontrolitem { nullptr }; TSubModel const *m_pickcontrolitem { nullptr };
TGroundNode const *m_picksceneryitem { nullptr }; TGroundNode const *m_picksceneryitem { nullptr };
#ifdef EU07_USE_DEBUG_CAMERA
renderpass_config m_worldcamera; // debug item
#endif
}; };
extern opengl_renderer GfxRenderer; extern opengl_renderer GfxRenderer;

19
sun.cpp
View File

@@ -33,9 +33,9 @@ void
cSun::update() { cSun::update() {
move(); move();
glm::vec3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor ); glm::vec3 position( 0.f, 0.f, -2000.f * Global::fDistanceFactor );
position = glm::rotateX( position, (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); position = glm::rotateX( position, glm::radians<float>( m_body.elevref ) );
position = glm::rotateY( position, (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); position = glm::rotateY( position, glm::radians<float>( -m_body.hrang ) );
m_position = position; m_position = position;
} }
@@ -251,21 +251,18 @@ void cSun::refract() {
void cSun::irradiance() { void cSun::irradiance() {
static double degrad = 57.295779513; // converts from radians to degrees
static double raddeg = 0.0174532925; // converts from degrees to radians
m_body.dayang = ( simulation::Time.year_day() - 1 ) * 360.0 / 365.0; m_body.dayang = ( simulation::Time.year_day() - 1 ) * 360.0 / 365.0;
double sd = sin( raddeg * m_body.dayang ); // sine of the day angle double sd = std::sin( glm::radians( m_body.dayang ) ); // sine of the day angle
double cd = cos( raddeg * m_body.dayang ); // cosine of the day angle or delination double cd = std::cos( glm::radians( m_body.dayang ) ); // cosine of the day angle or delination
m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd; m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd;
double d2 = 2.0 * m_body.dayang; double d2 = 2.0 * m_body.dayang;
double c2 = cos( raddeg * d2 ); double c2 = std::cos( glm::radians( d2 ) );
double s2 = sin( raddeg * d2 ); double s2 = std::sin( glm::radians( d2 ) );
m_body.erv += 0.000719*c2 + 0.000077*s2; m_body.erv += 0.000719*c2 + 0.000077*s2;
double solcon = 1367.0; // Solar constant, 1367 W/sq m double solcon = 1367.0; // Solar constant, 1367 W/sq m
m_body.coszen = cos( raddeg * m_body.zenref ); m_body.coszen = std::cos( glm::radians( m_body.zenref ) );
if( m_body.coszen > 0.0 ) { if( m_body.coszen > 0.0 ) {
m_body.etrn = solcon * m_body.erv; m_body.etrn = solcon * m_body.erv;
m_body.etr = m_body.etrn * m_body.coszen; m_body.etr = m_body.etrn * m_body.coszen;

View File

@@ -62,10 +62,10 @@ static std::unordered_map<std::string, std::string> m_cabcontrols = {
{ "converteroff_sw:", "converter" }, { "converteroff_sw:", "converter" },
{ "main_sw:", "line breaker" }, { "main_sw:", "line breaker" },
{ "radio_sw:", "radio" }, { "radio_sw:", "radio" },
{ "pantfront_sw:", "front pantograph" }, { "pantfront_sw:", "pantograph A" },
{ "pantrear_sw:", "rear pantograph" }, { "pantrear_sw:", "pantograph B" },
{ "pantfrontoff_sw:", "front pantograph" }, { "pantfrontoff_sw:", "pantograph A" },
{ "pantrearoff_sw:", "rear pantograph" }, { "pantrearoff_sw:", "pantograph B" },
{ "pantalloff_sw:", "all pantographs" }, { "pantalloff_sw:", "all pantographs" },
{ "pantselected_sw:", "selected pantograph" }, { "pantselected_sw:", "selected pantograph" },
{ "pantselectedoff_sw:", "selected pantograph" }, { "pantselectedoff_sw:", "selected pantograph" },

View File

@@ -65,7 +65,7 @@ ui_layer::render() {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glOrtho( 0, std::max( 1, Global::ScreenWidth ), std::max( 1, Global::ScreenHeight ), 0, -1, 1 ); glOrtho( 0, std::max( 1, Global::iWindowWidth ), std::max( 1, Global::iWindowHeight ), 0, -1, 1 );
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
@@ -78,6 +78,7 @@ ui_layer::render() {
// render code here // render code here
render_background(); render_background();
render_texture();
render_progress(); render_progress();
render_panels(); render_panels();
render_tooltip(); render_tooltip();
@@ -106,11 +107,7 @@ ui_layer::set_background( std::string const &Filename ) {
m_progressbottom = ( texture.width() != texture.height() ); m_progressbottom = ( texture.width() != texture.height() );
} }
} }
/*
void cGuiLayer::setNote( const std::string Note ) { mNote = Note; }
std::string cGuiLayer::getNote() { return mNote; }
*/
void void
ui_layer::render_progress() { ui_layer::render_progress() {
@@ -235,6 +232,32 @@ ui_layer::render_background() {
float4( 1.0f, 1.0f, 1.0f, 1.0f ) ); float4( 1.0f, 1.0f, 1.0f, 1.0f ) );
} }
void
ui_layer::render_texture() {
if( m_texture != NULL ) {
::glColor4f( 1.f, 1.f, 1.f, 1.f );
::glDisable( GL_BLEND );
GfxRenderer.Bind( NULL );
::glBindTexture( GL_TEXTURE_2D, m_texture );
auto const size = 512.f;
auto const offset = 64.f;
glBegin( GL_TRIANGLE_STRIP );
glMultiTexCoord2f( m_textureunit, 0.f, 1.f ); glVertex2f( offset, Global::iWindowHeight - offset - size );
glMultiTexCoord2f( m_textureunit, 0.f, 0.f ); glVertex2f( offset, Global::iWindowHeight - offset );
glMultiTexCoord2f( m_textureunit, 1.f, 1.f ); glVertex2f( offset + size, Global::iWindowHeight - offset - size );
glMultiTexCoord2f( m_textureunit, 1.f, 0.f ); glVertex2f( offset + size, Global::iWindowHeight - offset );
glEnd();
::glEnable( GL_BLEND );
}
}
void void
ui_layer::print( std::string const &Text ) ui_layer::print( std::string const &Text )
{ {

View File

@@ -24,8 +24,8 @@ struct ui_panel {
{} {}
std::vector<text_line> text_lines; std::vector<text_line> text_lines;
float origin_x; int origin_x;
float origin_y; int origin_y;
}; };
class ui_layer { class ui_layer {
@@ -54,6 +54,8 @@ public:
// sets the ui background texture, if any // sets the ui background texture, if any
void void
set_background( std::string const &Filename = "" ); set_background( std::string const &Filename = "" );
void
set_texture( GLuint Texture = NULL ) { m_texture = Texture; }
void void
set_tooltip( std::string const &Tooltip ) { m_tooltip = Tooltip; } set_tooltip( std::string const &Tooltip ) { m_tooltip = Tooltip; }
void void
@@ -68,6 +70,8 @@ private:
// draws background quad with specified earlier texture // draws background quad with specified earlier texture
void void
render_background(); render_background();
void
render_texture();
// draws a progress bar in defined earlier state // draws a progress bar in defined earlier state
void void
render_progress(); render_progress();
@@ -95,6 +99,7 @@ private:
bool m_progressbottom { false }; // location of the progress bar bool m_progressbottom { false }; // location of the progress bar
texture_handle m_background { NULL }; // path to texture used as the background. size depends on mAspect. texture_handle m_background { NULL }; // path to texture used as the background. size depends on mAspect.
GLuint m_texture { NULL };
std::vector<std::shared_ptr<ui_panel> > m_panels; std::vector<std::shared_ptr<ui_panel> > m_panels;
std::string m_tooltip; std::string m_tooltip;
}; };

View File

@@ -77,7 +77,22 @@ bool
degenerate( VecType_ const &Vertex1, VecType_ const &Vertex2, VecType_ const &Vertex3 ) { degenerate( VecType_ const &Vertex1, VecType_ const &Vertex2, VecType_ const &Vertex3 ) {
// degenerate( A, B, C, minarea ) = ( ( B - A ).cross( C - A ) ).lengthSquared() < ( 4.0f * minarea * minarea ); // degenerate( A, B, C, minarea ) = ( ( B - A ).cross( C - A ) ).lengthSquared() < ( 4.0f * minarea * minarea );
return glm::length2( glm::cross( Vertex2 - Vertex1, Vertex3 - Vertex1 ) ) < std::numeric_limits<VecType_::value_type>::epsilon(); return ( glm::length2( glm::cross( Vertex2 - Vertex1, Vertex3 - Vertex1 ) ) == 0.0 );
}
// calculates bounding box for provided set of points
template <class Iterator_, class VecType_>
void
bounding_box( VecType_ &Mincorner, VecType_ &Maxcorner, Iterator_ First, Iterator_ Last ) {
Mincorner = VecType_( typename std::numeric_limits<VecType_::value_type>::max() );
Maxcorner = VecType_( typename std::numeric_limits<VecType_::value_type>::lowest() );
std::for_each(
First, Last,
[&]( typename Iterator_::value_type &point ) {
Mincorner = glm::min( Mincorner, VecType_{ point } );
Maxcorner = glm::max( Maxcorner, VecType_{ point } ); } );
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 17 #define VERSION_MAJOR 17
#define VERSION_MINOR 725 #define VERSION_MINOR 805
#define VERSION_REVISION 0 #define VERSION_REVISION 0