16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-24 03:09:18 +02:00

merge (with bugs)

This commit is contained in:
VB
2017-04-24 19:08:08 +02:00
53 changed files with 2340 additions and 2233 deletions

View File

@@ -686,27 +686,19 @@ int TAnimModel::Flags()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów // 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef EU07_USE_OLD_RENDERCODE
void TAnimModel::RenderDL(vector3 *vPosition) void TAnimModel::RenderDL(vector3 *vPosition)
{ {
RaAnimate(); // jednorazowe przeliczenie animacji RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare(); RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli if( pModel ) // renderowanie rekurencyjne submodeli
#ifdef EU07_USE_OLD_RENDERCODE
pModel->Render(vPosition, &vAngle, ReplacableSkinId, iTexAlpha); pModel->Render(vPosition, &vAngle, ReplacableSkinId, iTexAlpha);
#else
GfxRenderer.Render( pModel, Material(), *vPosition, vAngle );
#endif
}; };
void TAnimModel::RenderAlphaDL(vector3 *vPosition) void TAnimModel::RenderAlphaDL(vector3 *vPosition)
{ {
RaPrepare(); RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli if (pModel) // renderowanie rekurencyjne submodeli
#ifdef EU07_USE_OLD_RENDERCODE
pModel->RenderAlpha(vPosition, &vAngle, ReplacableSkinId, iTexAlpha); pModel->RenderAlpha(vPosition, &vAngle, ReplacableSkinId, iTexAlpha);
#else
GfxRenderer.Render_Alpha( pModel, Material(), *vPosition, vAngle );
#endif
}; };
void TAnimModel::RenderVBO(vector3 *vPosition) void TAnimModel::RenderVBO(vector3 *vPosition)
@@ -714,15 +706,27 @@ void TAnimModel::RenderVBO(vector3 *vPosition)
RaAnimate(); // jednorazowe przeliczenie animacji RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare(); RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli if (pModel) // renderowanie rekurencyjne submodeli
pModel->RaRender(vPosition, &vAngle, Material()->replacable_skins, Material()->textures_alpha); pModel->RaRender( vPosition, &vAngle, Material()->replacable_skins, Material()->textures_alpha );
}; };
void TAnimModel::RenderAlphaVBO(vector3 *vPosition) void TAnimModel::RenderAlphaVBO(vector3 *vPosition)
{ {
RaPrepare(); RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli if (pModel) // renderowanie rekurencyjne submodeli
pModel->RaRenderAlpha(vPosition, &vAngle, Material()->replacable_skins, Material()->textures_alpha); pModel->RaRenderAlpha( vPosition, &vAngle, Material()->replacable_skins, Material()->textures_alpha );
}; };
#else
void TAnimModel::Render( vector3 *vPosition ) {
RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
GfxRenderer.Render( pModel, Material(), *vPosition, vAngle );
};
void TAnimModel::RenderAlpha( vector3 *vPosition ) {
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
GfxRenderer.Render_Alpha( pModel, Material(), *vPosition, vAngle );
};
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool TAnimModel::TerrainLoaded() bool TAnimModel::TerrainLoaded()

View File

@@ -175,10 +175,16 @@ class TAnimModel
void RenderAlphaDL(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0); void RenderAlphaDL(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
void RenderVBO(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0); void RenderVBO(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
void RenderAlphaVBO(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0); void RenderAlphaVBO(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
*/ void RenderDL(vector3 *vPosition); */
#ifdef EU07_USE_OLD_RENDERCODE
void RenderDL( vector3 *vPosition );
void RenderAlphaDL(vector3 *vPosition); void RenderAlphaDL(vector3 *vPosition);
void RenderVBO(vector3 *vPosition); void RenderVBO(vector3 *vPosition);
void RenderAlphaVBO(vector3 *vPosition); void RenderAlphaVBO(vector3 *vPosition);
#else
void Render( vector3 *vPosition );
void RenderAlpha( vector3 *vPosition );
#endif
int Flags(); int Flags();
void RaAnglesSet(double a, double b, double c) void RaAnglesSet(double a, double b, double c)
{ {

View File

@@ -64,6 +64,8 @@ set(SOURCES
"shader.cpp" "shader.cpp"
"frustum.cpp" "frustum.cpp"
"uilayer.cpp" "uilayer.cpp"
"openglmatrixstack.cpp"
"moon.cpp"
) )
if (WIN32) if (WIN32)

View File

@@ -111,12 +111,12 @@ vector3 TCamera::GetDirection()
return (Normalize(Vec)); return (Normalize(Vec));
} }
/*
bool TCamera::SetMatrix() bool TCamera::SetMatrix()
{ {
glRotated( -Roll * 180.0f / M_PI, 0, 0, 1 ); // po wyłączeniu tego kręci się pojazd, a sceneria nie 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.0f / M_PI, 1, 0, 0 ); glRotated( -Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0 );
glRotated( -Yaw * 180.0f / M_PI, 0, 1, 0 ); // w zewnętrznym widoku: kierunek patrzenia glRotated( -Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // w zewnętrznym widoku: kierunek patrzenia
if( Type == tp_Follow ) if( Type == tp_Follow )
{ {
@@ -132,7 +132,7 @@ bool TCamera::SetMatrix()
Global::SetCameraPosition(Pos); // było +pOffset Global::SetCameraPosition(Pos); // było +pOffset
return true; return true;
} }
*/
bool TCamera::SetMatrix( glm::mat4 &Matrix ) { bool TCamera::SetMatrix( glm::mat4 &Matrix ) {
Matrix = glm::rotate( Matrix, (float)-Roll, glm::vec3( 0.0f, 0.0f, 1.0f ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie Matrix = glm::rotate( Matrix, (float)-Roll, glm::vec3( 0.0f, 0.0f, 1.0f ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
@@ -157,9 +157,9 @@ bool TCamera::SetMatrix( glm::mat4 &Matrix ) {
void TCamera::SetCabMatrix(vector3 &p) void TCamera::SetCabMatrix(vector3 &p)
{ // ustawienie widoku z kamery bez przesunięcia robionego przez OpenGL - nie powinno tak trząść { // ustawienie widoku z kamery bez przesunięcia robionego przez OpenGL - nie powinno tak trząść
glRotated(-Roll * 180.0f / M_PI, 0, 0, 1); glRotated(-Roll * 180.0 / M_PI, 0.0, 0.0, 1.0);
glRotated(-Pitch * 180.0f / M_PI, 1, 0, 0); glRotated(-Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0);
glRotated(-Yaw * 180.0f / M_PI, 0, 1, 0); // w zewnętrznym widoku: kierunek patrzenia glRotated(-Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0); // w zewnętrznym widoku: kierunek patrzenia
if (Type == tp_Follow) if (Type == tp_Follow)
gluLookAt(Pos.x - p.x, Pos.y - p.y, Pos.z - p.z, LookAt.x - p.x, LookAt.y - p.y, gluLookAt(Pos.x - p.x, Pos.y - p.y, Pos.z - p.z, LookAt.x - p.x, LookAt.y - p.y,
LookAt.z - p.z, vUp.x, vUp.y, vUp.z); // Ra: pOffset is zero LookAt.z - p.z, vUp.x, vUp.y, vUp.z); // Ra: pOffset is zero

View File

@@ -48,9 +48,7 @@ class TCamera
void Update(); void Update();
vector3 GetDirection(); vector3 GetDirection();
// vector3 inline GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; }; // vector3 inline GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; };
/*
bool SetMatrix(); bool SetMatrix();
*/
bool SetMatrix(glm::mat4 &Matrix); bool SetMatrix(glm::mat4 &Matrix);
void SetCabMatrix( vector3 &p ); void SetCabMatrix( vector3 &p );
void RaLook(); void RaLook();

View File

@@ -36,9 +36,6 @@ class TMtableTime; // czas dla danego posterunku
}; };
class TController; // obiekt sterujący pociągiem (AI) class TController; // obiekt sterujący pociągiem (AI)
#ifdef EU07_USE_OLD_TNAMES_CLASS
class TNames; // obiekt sortujący nazwy
#endif
typedef enum typedef enum
{ // binarne odpowiedniki komend w komórce pamięci { // binarne odpowiedniki komend w komórce pamięci

View File

@@ -87,7 +87,7 @@ const double HardAcceleration = 0.9;
const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu
bool WriteLogFlag = false; bool WriteLogFlag = false;
string StopReasonTable[] = { std::string StopReasonTable[] = {
// przyczyny zatrzymania ruchu AI // przyczyny zatrzymania ruchu AI
"", // stopNone, //nie ma powodu - powinien jechać "", // stopNone, //nie ma powodu - powinien jechać
"Off", // stopSleep, //nie został odpalony, to nie pojedzie "Off", // stopSleep, //nie został odpalony, to nie pojedzie
@@ -240,23 +240,15 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
// głównej drogi - chyba że jest równorzędne... // głównej drogi - chyba że jest równorzędne...
fVelNext = 30.0; // uzależnić prędkość od promienia; albo niech będzie fVelNext = 30.0; // uzależnić prędkość od promienia; albo niech będzie
// ograniczona w skrzyżowaniu (velocity z ujemną wartością) // ograniczona w skrzyżowaniu (velocity z ujemną wartością)
if ((iFlags & spElapsed) == 0) // jeśli nie wjechał if( ( iFlags & spElapsed ) == 0 ) {
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY // jeśli nie wjechał
if (trTrack->iNumDynamics > 0) // a skrzyżowanie zawiera pojazd
{
if (Global::iWriteLogEnabled & 8)
WriteLog("Tor " + trTrack->NameGet() + " zajety przed pojazdem. Num=" + std::to_string(trTrack->iNumDynamics) + "Dist= " + std::to_string(fDist));
fVelNext =
0.0; // to zabronić wjazdu (chyba że ten z przodu też jedzie prosto)
}
#else
if( false == trTrack->Dynamics.empty() ) { if( false == trTrack->Dynamics.empty() ) {
if( Global::iWriteLogEnabled & 8 ) { if( Global::iWriteLogEnabled & 8 ) {
WriteLog( "Tor " + trTrack->NameGet() + " zajety przed pojazdem. Num=" + std::to_string( trTrack->Dynamics.size() ) + "Dist= " + std::to_string( fDist ) ); WriteLog( "Tor " + trTrack->NameGet() + " zajety przed pojazdem. Num=" + std::to_string( trTrack->Dynamics.size() ) + "Dist= " + std::to_string( fDist ) );
fVelNext = 0.0; // to zabronić wjazdu (chyba że ten z przodu też jedzie prosto) fVelNext = 0.0; // to zabronić wjazdu (chyba że ten z przodu też jedzie prosto)
} }
} }
#endif }
} }
if (iFlags & spSwitch) // jeśli odcinek zmienny if (iFlags & spSwitch) // jeśli odcinek zmienny
{ {
@@ -271,19 +263,6 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
// na Mydelniczce potrafi skanować na wprost mimo pojechania na bok // na Mydelniczce potrafi skanować na wprost mimo pojechania na bok
} }
// poniższe nie dotyczy trybu łączenia? // poniższe nie dotyczy trybu łączenia?
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if ((iFlags & spElapsed) ? false :
trTrack->iNumDynamics >
0) // jeśli jeszcze nie wjechano na tor, a coś na nim jest
{
if (Global::iWriteLogEnabled & 8)
WriteLog("Rozjazd " + trTrack->NameGet() + " zajety przed pojazdem. Num=" + std::to_string(trTrack->iNumDynamics) + "Dist= "+std::to_string(fDist));
//fDist -= 30.0;
fVelNext = 0.0; // to niech stanie w zwiększonej odległości
// else if (fVelNext==0.0) //jeśli została wyzerowana
// fVelNext=trTrack->VelocityGet(); //odczyt prędkości
}
#else
if( ( ( iFlags & spElapsed ) == 0 ) if( ( ( iFlags & spElapsed ) == 0 )
&& ( false == trTrack->Dynamics.empty() ) ) { && ( false == trTrack->Dynamics.empty() ) ) {
// jeśli jeszcze nie wjechano na tor, a coś na nim jest // jeśli jeszcze nie wjechano na tor, a coś na nim jest
@@ -292,7 +271,6 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
} }
fVelNext = 0.0; // to niech stanie w zwiększonej odległości fVelNext = 0.0; // to niech stanie w zwiększonej odległości
} }
#endif
} }
} }
} }
@@ -848,19 +826,16 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
{ // zaliczamy posterunek w pewnej odległości przed (choć W4 nie zasłania { // zaliczamy posterunek w pewnej odległości przed (choć W4 nie zasłania
// już semafora) // już semafora)
#if LOGSTOPS #if LOGSTOPS
WriteLog(pVehicle->asName + " as " + TrainParams->TrainName + ": at " + WriteLog(
std::to_string(GlobalTime->hh) + ":" + std::to_string(GlobalTime->mm) + pVehicle->asName + " as " + TrainParams->TrainName
" skipped " + asNextStop); // informacja + ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute)
+ " skipped " + asNextStop); // informacja
#endif #endif
fLastStopExpDist = mvOccupied->DistCounter + 0.250 + // przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
0.001 * fLength; // przy jakim dystansie (stanie fLastStopExpDist = mvOccupied->DistCounter + 0.250 + 0.001 * fLength;
// licznika) ma przesunąć na TrainParams->UpdateMTable( Simulation::Time, asNextStop );
// następny postój
TrainParams->UpdateMTable(
GlobalTime->hh, GlobalTime->mm, asNextStop);
TrainParams->StationIndexInc(); // przejście do następnej TrainParams->StationIndexInc(); // przejście do następnej
asNextStop = asNextStop = TrainParams->NextStop(); // pobranie kolejnego miejsca zatrzymania
TrainParams->NextStop(); // pobranie kolejnego miejsca zatrzymania
// TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie // TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie
// jest dobry pomysł // jest dobry pomysł
sSpeedTable[i].iFlags = 0; // nie liczy się już sSpeedTable[i].iFlags = 0; // nie liczy się już
@@ -955,8 +930,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// niezależne od sposobu obsługi drzwi, bo // niezależne od sposobu obsługi drzwi, bo
// opóźnia również kierownika // opóźnia również kierownika
} }
if (TrainParams->UpdateMTable( if (TrainParams->UpdateMTable( Simulation::Time, asNextStop) )
GlobalTime->hh, GlobalTime->mm, asNextStop) )
{ // to się wykona tylko raz po zatrzymaniu na W4 { // to się wykona tylko raz po zatrzymaniu na W4
if (TrainParams->CheckTrainLatency() < 0.0) if (TrainParams->CheckTrainLatency() < 0.0)
iDrivigFlags |= moveLate; // odnotowano spóźnienie iDrivigFlags |= moveLate; // odnotowano spóźnienie
@@ -1002,7 +976,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if (TrainParams->StationIndex < TrainParams->StationCount) if (TrainParams->StationIndex < TrainParams->StationCount)
{ // jeśli są dalsze stacje, czekamy do godziny odjazdu { // jeśli są dalsze stacje, czekamy do godziny odjazdu
if (TrainParams->IsTimeToGo(GlobalTime->hh, GlobalTime->mm)) if (TrainParams->IsTimeToGo(Simulation::Time.data().wHour, Simulation::Time.data().wMinute))
{ // z dalszą akcją czekamy do godziny odjazdu { // z dalszą akcją czekamy do godziny odjazdu
/* potencjalny problem z ruszaniem z w4 /* potencjalny problem z ruszaniem z w4
if (TrainParams->CheckTrainLatency() < 0) if (TrainParams->CheckTrainLatency() < 0)
@@ -1019,10 +993,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
asNextStop = TrainParams->NextStop(); // pobranie kolejnego miejsca zatrzymania asNextStop = TrainParams->NextStop(); // pobranie kolejnego miejsca zatrzymania
// TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie jest dobry pomysł // TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie jest dobry pomysł
#if LOGSTOPS #if LOGSTOPS
WriteLog(pVehicle->asName + " as " + TrainParams->TrainName + WriteLog(
": at " + std::to_string(GlobalTime->hh) + ":" + pVehicle->asName + " as " + TrainParams->TrainName
std::to_string(GlobalTime->mm) + " next " + + ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute)
asNextStop); // informacja + " next " + asNextStop); // informacja
#endif #endif
if (int(floor(sSpeedTable[i].evEvent->ValueGet(1))) & 1) if (int(floor(sSpeedTable[i].evEvent->ValueGet(1))) & 1)
iDrivigFlags |= moveStopHere; // nie podjeżdżać do semafora, iDrivigFlags |= moveStopHere; // nie podjeżdżać do semafora,
@@ -1046,10 +1020,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
else else
{ // jeśli dojechaliśmy do końca rozkładu { // jeśli dojechaliśmy do końca rozkładu
#if LOGSTOPS #if LOGSTOPS
WriteLog(pVehicle->asName + " as " + TrainParams->TrainName + WriteLog(
": at " + std::to_string(GlobalTime->hh) + ":" + pVehicle->asName + " as " + TrainParams->TrainName
std::to_string(GlobalTime->mm) + + ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute)
" end of route."); // informacja + " end of route."); // informacja
#endif #endif
asNextStop = TrainParams->NextStop(); // informacja o końcu trasy asNextStop = TrainParams->NextStop(); // informacja o końcu trasy
TrainParams->NewName("none"); // czyszczenie nieaktualnego rozkładu TrainParams->NewName("none"); // czyszczenie nieaktualnego rozkładu
@@ -1504,10 +1478,10 @@ TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche,
if( WriteLogFlag ) { if( WriteLogFlag ) {
mkdir( "physicslog\\" ); mkdir( "physicslog\\" );
LogFile.open( string( "physicslog\\" + VehicleName + ".dat" ).c_str(), LogFile.open( std::string( "physicslog\\" + VehicleName + ".dat" ).c_str(),
std::ios::in | std::ios::out | std::ios::trunc ); std::ios::in | std::ios::out | std::ios::trunc );
#if LOGPRESS == 0 #if LOGPRESS == 0
LogFile << string( " Time [s] Velocity [m/s] Acceleration [m/ss] Coupler.Dist[m] " LogFile << std::string( " Time [s] Velocity [m/s] Acceleration [m/ss] Coupler.Dist[m] "
"Coupler.Force[N] TractionForce [kN] FrictionForce [kN] " "Coupler.Force[N] TractionForce [kN] FrictionForce [kN] "
"BrakeForce [kN] BrakePress [MPa] PipePress [MPa] " "BrakeForce [kN] BrakePress [MPa] PipePress [MPa] "
"MotorCurrent [A] MCP SCP BCP LBP DmgFlag Command CVal1 CVal2" ) "MotorCurrent [A] MCP SCP BCP LBP DmgFlag Command CVal1 CVal2" )
@@ -1698,7 +1672,7 @@ void TController::AutoRewident()
ustaw = 16 + bdelay_R; // lokomotywa luzem (może być wieloczłonowa) ustaw = 16 + bdelay_R; // lokomotywa luzem (może być wieloczłonowa)
else else
{ // jeśli są wagony { // jeśli są wagony
ustaw = (g < min(4, r + p) ? 16 : 0); ustaw = (g < std::min(4, r + p) ? 16 : 0);
if (ustaw) // jeśli towarowe < Min(4, pospieszne+osobowe) if (ustaw) // jeśli towarowe < Min(4, pospieszne+osobowe)
{ // to skład pasażerski - nastawianie pasażerskiego { // to skład pasażerski - nastawianie pasażerskiego
ustaw += (g && (r < g + p)) ? bdelay_P : bdelay_R; ustaw += (g && (r < g + p)) ? bdelay_P : bdelay_R;
@@ -2891,8 +2865,7 @@ bool TController::PutCommand(std::string NewCommand, double NewValue1, double Ne
} }
else else
{ // inicjacja pierwszego przystanku i pobranie jego nazwy { // inicjacja pierwszego przystanku i pobranie jego nazwy
TrainParams->UpdateMTable(GlobalTime->hh, GlobalTime->mm, TrainParams->UpdateMTable( Simulation::Time, TrainParams->NextStationName );
TrainParams->NextStationName);
TrainParams->StationIndexInc(); // przejście do następnej TrainParams->StationIndexInc(); // przejście do następnej
iStationStart = TrainParams->StationIndex; iStationStart = TrainParams->StationIndex;
asNextStop = TrainParams->NextStop(); asNextStop = TrainParams->NextStop();
@@ -4927,7 +4900,7 @@ void TController::OrdersInit(double fVel)
// Ale mozna by je zapodac ze scenerii // Ale mozna by je zapodac ze scenerii
}; };
string TController::StopReasonText() std::string TController::StopReasonText()
{ // informacja tekstowa o przyczynie zatrzymania { // informacja tekstowa o przyczynie zatrzymania
if (eStopReason != 7) // zawalidroga będzie inaczej if (eStopReason != 7) // zawalidroga będzie inaczej
return StopReasonTable[eStopReason]; return StopReasonTable[eStopReason];
@@ -4952,15 +4925,6 @@ double TController::Distance(vector3 &p1,vector3 &n,vector3 &p2)
bool TController::BackwardTrackBusy(TTrack *Track) bool TController::BackwardTrackBusy(TTrack *Track)
{ // najpierw sprawdzamy, czy na danym torze są pojazdy z innego składu { // najpierw sprawdzamy, czy na danym torze są pojazdy z innego składu
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if (Track->iNumDynamics)
{ // jeśli tylko z własnego składu, to tor jest wolny
for (int i = 0; i < Track->iNumDynamics; ++i)
if (Track->Dynamics[i]->ctOwner != this) // jeśli jest jakiś cudzy
return true; // to tor jest zajęty i skanowanie nie obowiązuje
}
return false; // wolny
#else
if( false == Track->Dynamics.empty() ) { if( false == Track->Dynamics.empty() ) {
for( auto dynamic : Track->Dynamics ) { for( auto dynamic : Track->Dynamics ) {
if( dynamic->ctOwner != this ) { if( dynamic->ctOwner != this ) {
@@ -4970,7 +4934,6 @@ bool TController::BackwardTrackBusy(TTrack *Track)
} }
} }
return false; // wolny return false; // wolny
#endif
}; };
TEvent * TController::CheckTrackEventBackward(double fDirection, TTrack *Track) TEvent * TController::CheckTrackEventBackward(double fDirection, TTrack *Track)
@@ -5435,5 +5398,5 @@ void TController::RouteSwitch(int d)
}; };
std::string TController::OwnerName() std::string TController::OwnerName()
{ {
return pVehicle ? pVehicle->MoverParameters->Name : string("none"); return ( pVehicle ? pVehicle->MoverParameters->Name : "none" );
}; };

View File

@@ -950,69 +950,15 @@ double ABuAcos(const vector3 &calc_temp)
return atan2(-calc_temp.x, calc_temp.z); // Ra: tak prościej return atan2(-calc_temp.x, calc_temp.z); // Ra: tak prościej
} }
TDynamicObject * TDynamicObject::ABuFindNearestObject(TTrack *Track, TDynamicObject * TDynamicObject::ABuFindNearestObject(TTrack *Track, TDynamicObject *MyPointer, int &CouplNr)
TDynamicObject *MyPointer, {
int &CouplNr) // zwraca wskaznik do obiektu znajdujacego sie na torze (Track), którego sprzęg jest najblizszy kamerze
{ // zwraca wskaznik do obiektu znajdujacego sie na torze
// (Track), którego sprzęg jest najblizszy
// kamerze
// służy np. do łączenia i rozpinania sprzęgów // służy np. do łączenia i rozpinania sprzęgów
// WE: Track - tor, na ktorym odbywa sie poszukiwanie // WE: Track - tor, na ktorym odbywa sie poszukiwanie
// MyPointer - wskaznik do obiektu szukajacego // MyPointer - wskaznik do obiektu szukajacego
// WY: CouplNr - który sprzęg znalezionego obiektu jest bliższy kamerze // WY: CouplNr - który sprzęg znalezionego obiektu jest bliższy kamerze
// Uwaga! Jesli CouplNr==-2 to szukamy njblizszego obiektu, a nie sprzegu!!! // Uwaga! Jesli CouplNr==-2 to szukamy njblizszego obiektu, a nie sprzegu!!!
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if ((Track->iNumDynamics) > 0)
{ // o ile w ogóle jest co przeglądać na tym torze
// vector3 poz; //pozycja pojazdu XYZ w scenerii
// vector3 kon; //wektor czoła względem środka pojazdu wzglęem początku toru
vector3 tmp; // wektor pomiędzy kamerą i sprzęgiem
double dist; // odległość
for (int i = 0; i < Track->iNumDynamics; i++)
{
if (CouplNr == -2)
{ // wektor [kamera-obiekt] - poszukiwanie obiektu
tmp = Global::GetCameraPosition() - Track->Dynamics[i]->vPosition;
dist = tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z; // odległość do kwadratu
if (dist < 100.0) // 10 metrów
return Track->Dynamics[i];
}
else // jeśli (CouplNr) inne niz -2, szukamy sprzęgu
{ // wektor [kamera-sprzeg0], potem [kamera-sprzeg1]
// Powinno byc wyliczone, ale nie zaszkodzi drugi raz:
//(bo co, jesli nie wykonuje sie obrotow wozkow?) - Ra: ale zawsze są
// liczone
// współrzędne sprzęgów
// Track->Dynamics[i]->modelRot.z=ABuAcos(Track->Dynamics[i]->Axle0.pPosition-Track->Dynamics[i]->Axle1.pPosition);
// poz=Track->Dynamics[i]->vPosition; //pozycja środka pojazdu
// kon=vector3( //położenie przodu względem środka
// -((0.5*Track->Dynamics[i]->MoverParameters->Dim.L)*sin(Track->Dynamics[i]->modelRot.z)),
// 0, //yyy... jeśli duże pochylenie i długi pojazd, to może być problem
// +((0.5*Track->Dynamics[i]->MoverParameters->Dim.L)*cos(Track->Dynamics[i]->modelRot.z))
//);
tmp =
Global::GetCameraPosition() -
Track->Dynamics[i]->vCoulpler[0]; // Ra: pozycje sprzęgów też są zawsze liczone
dist = tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z; // odległość do kwadratu
if (dist < 25.0) // 5 metrów
{
CouplNr = 0;
return Track->Dynamics[i];
}
tmp = Global::GetCameraPosition() - Track->Dynamics[i]->vCoulpler[1];
dist = tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z; // odległość do kwadratu
if (dist < 25.0) // 5 metrów
{
CouplNr = 1;
return Track->Dynamics[i];
}
}
}
return NULL;
}
#else
for( auto dynamic : Track->Dynamics ) { for( auto dynamic : Track->Dynamics ) {
if( CouplNr == -2 ) { if( CouplNr == -2 ) {
@@ -1038,7 +984,6 @@ TDynamicObject * TDynamicObject::ABuFindNearestObject(TTrack *Track,
} }
// empty track or nothing found // empty track or nothing found
return nullptr; return nullptr;
#endif
} }
TDynamicObject * TDynamicObject::ABuScanNearestObject(TTrack *Track, double ScanDir, TDynamicObject * TDynamicObject::ABuScanNearestObject(TTrack *Track, double ScanDir,
@@ -1160,21 +1105,13 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
// WY: wskaznik do znalezionego obiektu. // WY: wskaznik do znalezionego obiektu.
// CouplFound - nr sprzegu znalezionego obiektu // CouplFound - nr sprzegu znalezionego obiektu
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if (Track->iNumDynamics > 0)
#else
if( false == Track->Dynamics.empty() ) if( false == Track->Dynamics.empty() )
#endif
{ // sens szukania na tym torze jest tylko, gdy są na nim pojazdy { // sens szukania na tym torze jest tylko, gdy są na nim pojazdy
double MyTranslation; // pozycja szukającego na torze double MyTranslation; // pozycja szukającego na torze
double MinDist = Track->Length(); // najmniejsza znaleziona odleglość double MinDist = Track->Length(); // najmniejsza znaleziona odleglość
// (zaczynamy od długości toru) // (zaczynamy od długości toru)
double TestDist; // robocza odległość od kolejnych pojazdów na danym odcinku double TestDist; // robocza odległość od kolejnych pojazdów na danym odcinku
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
int iMinDist = -1; // indeks wykrytego obiektu
#else
TDynamicObject *collider = nullptr; TDynamicObject *collider = nullptr;
#endif
// if (Track->iNumDynamics>1) // if (Track->iNumDynamics>1)
// iMinDist+=0; //tymczasowo pułapka // iMinDist+=0; //tymczasowo pułapka
if (MyTrack == Track) // gdy szukanie na tym samym torze if (MyTrack == Track) // gdy szukanie na tym samym torze
@@ -1186,54 +1123,6 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
MyTranslation = MinDist; // szukanie w kierunku Point1 (do zera) - jesteśmy w Point2 MyTranslation = MinDist; // szukanie w kierunku Point1 (do zera) - jesteśmy w Point2
if (ScanDir >= 0) if (ScanDir >= 0)
{ // jeśli szukanie w kierunku Point2 { // jeśli szukanie w kierunku Point2
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for( int i = 0; i < Track->iNumDynamics; i++ )
{ // pętla po pojazdach
if (Track->Dynamics[i] != this) // szukający się nie liczy
{
TestDist = (Track->Dynamics[i]->RaTranslationGet()) -
MyTranslation; // odległogłość tamtego od szukającego
if ((TestDist > 0) && (TestDist <= MinDist))
{ // gdy jest po właściwej stronie i bliżej
// niż jakiś wcześniejszy
CouplFound = (Track->Dynamics[i]->RaDirectionGet() > 0) ?
1 :
0; // to, bo (ScanDir>=0)
if (Track->iCategoryFlag & 254) // trajektoria innego typu niż tor kolejowy
{ // dla torów nie ma sensu tego sprawdzać, rzadko co jedzie po
// jednej
// szynie i się mija
// Ra: mijanie samochodów wcale nie jest proste
// Przesuniecie wzgledne pojazdow. Wyznaczane, zeby sprawdzic,
// czy pojazdy faktycznie sie zderzaja (moga byc przesuniete
// w/m siebie tak, ze nie zachodza na siebie i wtedy sie mijaja).
double RelOffsetH; // wzajemna odległość poprzeczna
if (CouplFound) // my na tym torze byśmy byli w kierunku Point2
// dla CouplFound=1 są zwroty zgodne - istotna różnica
// przesunięć
RelOffsetH = (MoverParameters->OffsetTrackH -
Track->Dynamics[i]->MoverParameters->OffsetTrackH);
else
// dla CouplFound=0 są zwroty przeciwne - przesunięcia sumują
// się
RelOffsetH = (MoverParameters->OffsetTrackH +
Track->Dynamics[i]->MoverParameters->OffsetTrackH);
if (RelOffsetH < 0)
RelOffsetH = -RelOffsetH;
if (RelOffsetH + RelOffsetH >
MoverParameters->Dim.W + Track->Dynamics[i]->MoverParameters->Dim.W)
continue; // odległość większa od połowy sumy szerokości -
// kolizji
// nie będzie
// jeśli zahaczenie jest niewielkie, a jest miejsce na poboczu, to
// zjechać na pobocze
}
iMinDist = i; // potencjalna kolizja
MinDist = TestDist; // odleglość pomiędzy aktywnymi osiami pojazdów
}
}
}
#else
for( auto dynamic : Track->Dynamics ) { for( auto dynamic : Track->Dynamics ) {
// pętla po pojazdach // pętla po pojazdach
if( dynamic == this ) { if( dynamic == this ) {
@@ -1277,56 +1166,9 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
} }
} }
#endif
} }
else //(ScanDir<0) else //(ScanDir<0)
{ {
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for( int i = 0; i < Track->iNumDynamics; i++ )
{
if (Track->Dynamics[i] != this)
{
TestDist = MyTranslation -
(Track->Dynamics[i]->RaTranslationGet()); //???-przesunięcie wózka
// względem Point1 toru
if ((TestDist > 0) && (TestDist < MinDist))
{
CouplFound = (Track->Dynamics[i]->RaDirectionGet() > 0) ?
0 :
1; // odwrotnie, bo (ScanDir<0)
if (Track->iCategoryFlag & 254) // trajektoria innego typu niż tor kolejowy
{ // dla torów nie ma sensu tego sprawdzać, rzadko co jedzie po
// jednej
// szynie i się mija
// Ra: mijanie samochodów wcale nie jest proste
// Przesunięcie względne pojazdów. Wyznaczane, żeby sprawdzić,
// czy pojazdy faktycznie się zderzają (mogą być przesunięte
// w/m siebie tak, że nie zachodzą na siebie i wtedy sie mijają).
double RelOffsetH; // wzajemna odległość poprzeczna
if (CouplFound) // my na tym torze byśmy byli w kierunku Point1
// dla CouplFound=1 są zwroty zgodne - istotna różnica
// przesunięć
RelOffsetH = (MoverParameters->OffsetTrackH -
Track->Dynamics[i]->MoverParameters->OffsetTrackH);
else
// dla CouplFound=0 są zwroty przeciwne - przesunięcia sumują
// się
RelOffsetH = (MoverParameters->OffsetTrackH +
Track->Dynamics[i]->MoverParameters->OffsetTrackH);
if (RelOffsetH < 0)
RelOffsetH = -RelOffsetH;
if (RelOffsetH + RelOffsetH >
MoverParameters->Dim.W + Track->Dynamics[i]->MoverParameters->Dim.W)
continue; // odległość większa od połowy sumy szerokości -
// kolizji
// nie będzie
}
iMinDist = i; // potencjalna kolizja
MinDist = TestDist; // odleglość pomiędzy aktywnymi osiami pojazdów
}
}
}
#else
for( auto dynamic : Track->Dynamics ) { for( auto dynamic : Track->Dynamics ) {
if( dynamic == this ) { continue; } if( dynamic == this ) { continue; }
@@ -1362,14 +1204,9 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
MinDist = TestDist; // odleglość pomiędzy aktywnymi osiami pojazdów MinDist = TestDist; // odleglość pomiędzy aktywnymi osiami pojazdów
} }
} }
#endif
} }
dist += MinDist; // doliczenie odległości przeszkody albo długości odcinka do przeskanowanej odległości dist += MinDist; // doliczenie odległości przeszkody albo długości odcinka do przeskanowanej odległości
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
return ( iMinDist >= 0 ) ? Track->Dynamics[ iMinDist ] : NULL;
#else
return collider; return collider;
#endif
} }
dist += Track->Length(); // doliczenie długości odcinka do przeskanowanej dist += Track->Length(); // doliczenie długości odcinka do przeskanowanej
// odległości // odległości
@@ -2451,19 +2288,18 @@ void TDynamicObject::AttachPrev(TDynamicObject *Object, int iType)
Object->NextConnected = this; // on ma nas z tyłu Object->NextConnected = this; // on ma nas z tyłu
Object->NextConnectedNo = iDirection; Object->NextConnectedNo = iDirection;
} }
/*
// NOTE: this appears unnecessary and only messes things for the programmable lights function, which walks along
// whole trainset and expects each module to point to its own lights. Disabled, TBD, TODO: test for side-effects and delete if there's none
if (MoverParameters->TrainType & dt_EZT) // w przypadku łączenia członów, if (MoverParameters->TrainType & dt_EZT) // w przypadku łączenia członów,
// światła w rozrządczym zależą od // światła w rozrządczym zależą od stanu w silnikowym
// stanu w silnikowym if (MoverParameters->Couplers[iDirection].AllowedFlag & ctrain_depot) // gdy sprzęgi łączone warsztatowo (powiedzmy)
if (MoverParameters->Couplers[iDirection].AllowedFlag & if ((MoverParameters->Power < 1.0) && (Object->MoverParameters->Power > 1.0)) // my nie mamy mocy, ale ten drugi ma
ctrain_depot) // gdy sprzęgi łączone warsztatowo (powiedzmy) iLights = Object->MoverParameters->iLights; // to w tym z mocą będą światła załączane, a w tym bez tylko widoczne
if ((MoverParameters->Power < 1.0) &&
(Object->MoverParameters->Power > 1.0)) // my nie mamy mocy, ale ten drugi ma
iLights = Object->MoverParameters->iLights; // to w tym z mocą będą światła
// załączane, a w tym bez tylko widoczne
else if ((MoverParameters->Power > 1.0) && else if ((MoverParameters->Power > 1.0) &&
(Object->MoverParameters->Power < 1.0)) // my mamy moc, ale ten drugi nie ma (Object->MoverParameters->Power < 1.0)) // my mamy moc, ale ten drugi nie ma
Object->iLights = MoverParameters->iLights; // to w tym z mocą będą światła Object->iLights = MoverParameters->iLights; // to w tym z mocą będą światła załączane, a w tym bez tylko widoczne
// załączane, a w tym bez tylko widoczne */
return; return;
// SetPneumatic(1,1); //Ra: to i tak się nie wykonywało po return // SetPneumatic(1,1); //Ra: to i tak się nie wykonywało po return
// SetPneumatic(1,0); // SetPneumatic(1,0);

View File

@@ -36,21 +36,13 @@ TEventLauncher::TEventLauncher()
DeltaTime = -1; DeltaTime = -1;
UpdatedTime = 0; UpdatedTime = 0;
fVal1 = fVal2 = 0; fVal1 = fVal2 = 0;
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
szText = NULL;
#endif
iHour = iMinute = -1; // takiego czasu nigdy nie będzie iHour = iMinute = -1; // takiego czasu nigdy nie będzie
dRadius = 0; dRadius = 0;
Event1 = Event2 = NULL; Event1 = Event2 = NULL;
MemCell = NULL; MemCell = NULL;
iCheckMask = 0; iCheckMask = 0;
} }
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
TEventLauncher::~TEventLauncher()
{
SafeDeleteArray(szText);
}
#endif
void TEventLauncher::Init() void TEventLauncher::Init()
{ {
} }
@@ -126,13 +118,7 @@ bool TEventLauncher::Load(cParser *parser)
asMemCellName = token; asMemCellName = token;
parser->getTokens(); parser->getTokens();
*parser >> token; *parser >> token;
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
SafeDeleteArray(szText);
szText = new char[256];
strcpy(szText, token.c_str());
#else
szText = token; szText = token;
#endif
if (token != "*") //*=nie brać command pod uwagę if (token != "*") //*=nie brać command pod uwagę
iCheckMask |= conditional_memstring; iCheckMask |= conditional_memstring;
parser->getTokens(); parser->getTokens();
@@ -189,9 +175,9 @@ bool TEventLauncher::Render()
} }
else else
{ // jeśli nie cykliczny, to sprawdzić czas { // jeśli nie cykliczny, to sprawdzić czas
if (GlobalTime->hh == iHour) if (Simulation::Time.data().wHour == iHour)
{ {
if (GlobalTime->mm == iMinute) if (Simulation::Time.data().wMinute == iMinute)
{ // zgodność czasu uruchomienia { // zgodność czasu uruchomienia
if (UpdatedTime < 10) if (UpdatedTime < 10)
{ {

View File

@@ -7,8 +7,7 @@ obtain one at
http://mozilla.org/MPL/2.0/. http://mozilla.org/MPL/2.0/.
*/ */
#ifndef EvLaunchH #pragma once
#define EvLaunchH
#include <string> #include <string>
#include "Classes.h" #include "Classes.h"
@@ -21,11 +20,7 @@ class TEventLauncher
double UpdatedTime; double UpdatedTime;
double fVal1; double fVal1;
double fVal2; double fVal2;
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
char * szText;
#else
std::string szText; std::string szText;
#endif
int iHour, iMinute; // minuta uruchomienia int iHour, iMinute; // minuta uruchomienia
public: public:
double dRadius; double dRadius;
@@ -37,9 +32,6 @@ class TEventLauncher
TMemCell *MemCell; TMemCell *MemCell;
int iCheckMask; int iCheckMask;
TEventLauncher(); TEventLauncher();
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
~TEventLauncher();
#endif
void Init(); void Init();
bool Load(cParser *parser); bool Load(cParser *parser);
bool Render(); bool Render();
@@ -47,4 +39,3 @@ class TEventLauncher
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif

View File

@@ -70,7 +70,7 @@ void TEvent::Init(){
}; };
void TEvent::Conditions(cParser *parser, string s) void TEvent::Conditions(cParser *parser, std::string s)
{ // przetwarzanie warunków, wspólne dla Multiple i UpdateValues { // przetwarzanie warunków, wspólne dla Multiple i UpdateValues
if (s == "condition") if (s == "condition")
{ // jesli nie "endevent" { // jesli nie "endevent"
@@ -623,14 +623,14 @@ void TEvent::AddToQuery(TEvent *e)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
string TEvent::CommandGet() std::string TEvent::CommandGet()
{ // odczytanie komendy z eventu { // odczytanie komendy z eventu
switch (Type) switch (Type)
{ // to się wykonuje również składu jadącego bez obsługi { // to się wykonuje również składu jadącego bez obsługi
case tp_GetValues: case tp_GetValues:
return string(Params[9].asMemCell->Text()); return std::string(Params[9].asMemCell->Text());
case tp_PutValues: case tp_PutValues:
return string(Params[0].asText); return std::string(Params[0].asText);
} }
return ""; // inne eventy się nie liczą return ""; // inne eventy się nie liczą
}; };

View File

@@ -78,11 +78,12 @@ double Global::pCameraRotation;
double Global::pCameraRotationDeg; double Global::pCameraRotationDeg;
std::vector<vector3> Global::FreeCameraInit; std::vector<vector3> Global::FreeCameraInit;
std::vector<vector3> Global::FreeCameraInitAngle; std::vector<vector3> Global::FreeCameraInitAngle;
double Global::fFogStart = 1700;
double Global::fFogEnd = 2000;
float Global::Background[3] = {0.2f, 0.4f, 0.33f}; float Global::Background[3] = {0.2f, 0.4f, 0.33f};
GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f}; GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f};
GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f}; GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
double Global::fFogStart = 1700;
double Global::fFogEnd = 2000;
float Global::Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
#ifdef EU07_USE_OLD_LIGHTING_MODEL #ifdef EU07_USE_OLD_LIGHTING_MODEL
GLfloat Global::ambientDayLight[] = {0.40f, 0.40f, 0.45f, 1.0f}; // robocze GLfloat Global::ambientDayLight[] = {0.40f, 0.40f, 0.45f, 1.0f}; // robocze
GLfloat Global::diffuseDayLight[] = {0.55f, 0.54f, 0.50f, 1.0f}; GLfloat Global::diffuseDayLight[] = {0.55f, 0.54f, 0.50f, 1.0f};
@@ -134,7 +135,6 @@ int Global::iDefaultFiltering = 9; // domyślne rozmywanie tekstur TGA bez alfa
int Global::iBallastFiltering = 9; // domyślne rozmywanie tekstur podsypki int Global::iBallastFiltering = 9; // domyślne rozmywanie tekstur podsypki
int Global::iRailProFiltering = 5; // domyślne rozmywanie tekstur szyn int Global::iRailProFiltering = 5; // domyślne rozmywanie tekstur szyn
int Global::iDynamicFiltering = 5; // domyślne rozmywanie tekstur pojazdów int Global::iDynamicFiltering = 5; // domyślne rozmywanie tekstur pojazdów
bool Global::bUseVBO = true; // czy jest VBO w karcie graficznej (czy użyć)
std::string Global::LastGLError; std::string Global::LastGLError;
GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury
bool Global::bSmoothTraction = false; // wygładzanie drutów starym sposobem bool Global::bSmoothTraction = false; // wygładzanie drutów starym sposobem
@@ -480,13 +480,6 @@ void Global::ConfigParse(cParser &Parser)
Parser.getTokens( 1, false ); Parser.getTokens( 1, false );
Parser >> Global::AnisotropicFiltering; Parser >> Global::AnisotropicFiltering;
} }
else if( token == "usevbo" )
{
/*
Parser.getTokens();
Parser >> Global::bUseVBO;
*/
}
else if (token == "feedbackmode") else if (token == "feedbackmode")
{ {

View File

@@ -218,6 +218,7 @@ class Global
static float Background[3]; static float Background[3];
static GLfloat AtmoColor[]; static GLfloat AtmoColor[];
static GLfloat FogColor[]; static GLfloat FogColor[];
static float Overcast;
// static bool bTimeChange; // static bool bTimeChange;
#ifdef EU07_USE_OLD_LIGHTING_MODEL #ifdef EU07_USE_OLD_LIGHTING_MODEL
static opengl_light AmbientLight; static opengl_light AmbientLight;
@@ -248,7 +249,6 @@ class Global
static int iRailProFiltering; // domyślne rozmywanie tekstury szyn static int iRailProFiltering; // domyślne rozmywanie tekstury szyn
static int iDynamicFiltering; // domyślne rozmywanie tekstur pojazdów static int iDynamicFiltering; // domyślne rozmywanie tekstur pojazdów
static int iReCompile; // zwiększany, gdy trzeba odświeżyć siatki static int iReCompile; // zwiększany, gdy trzeba odświeżyć siatki
static bool bUseVBO; // czy jest VBO w karcie graficznej
static std::string LastGLError; static std::string LastGLError;
static int iFeedbackMode; // tryb pracy informacji zwrotnej static int iFeedbackMode; // tryb pracy informacji zwrotnej
static int iFeedbackPort; // dodatkowy adres dla informacji zwrotnych static int iFeedbackPort; // dodatkowy adres dla informacji zwrotnych
@@ -360,10 +360,9 @@ class Global
struct daylight_s struct daylight_s
{ {
float3 position; glm::vec3 ambient;
float3 direction; glm::vec3 direction;
float3 color; glm::vec3 color;
float3 ambient;
float intensity; float intensity;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -300,21 +300,12 @@ class TGround
// TGroundNode *nLastOfType[TP_LAST]; //ostatnia // TGroundNode *nLastOfType[TP_LAST]; //ostatnia
TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe) TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe)
int hh = 0, int hh = 0,
mm = 0, mm = 0; // ustawienia czasu
srh = 0,
srm = 0,
ssh = 0,
ssm = 0; // ustawienia czasu
// int tracks,tracksfar; //liczniki torów // int tracks,tracksfar; //liczniki torów
#ifdef EU07_USE_OLD_TNAMES_CLASS
TNames *sTracks = nullptr; // posortowane nazwy torów i eventów
#else
typedef std::unordered_map<std::string, TEvent *> event_map; typedef std::unordered_map<std::string, TEvent *> event_map;
event_map m_eventmap; event_map m_eventmap;
TNames<TGroundNode *> m_trackmap; TNames<TGroundNode *> m_trackmap;
#endif light_array m_lights; // collection of dynamic light sources present in the scene
light_array m_lights;
private: // metody prywatne private: // metody prywatne
bool EventConditon(TEvent *e); bool EventConditon(TEvent *e);

View File

@@ -28,37 +28,20 @@ http://mozilla.org/MPL/2.0/.
TMemCell::TMemCell(vector3 *p) TMemCell::TMemCell(vector3 *p)
{ {
fValue1 = fValue2 = 0; fValue1 = fValue2 = 0;
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
szText = new char[256]; // musi być dla automatycznie tworzonych komórek dla odcinków izolowanych
#endif
vPosition = vPosition =
p ? *p : vector3(0, 0, 0); // ustawienie współrzędnych, bo do TGroundNode nie ma dostępu p ? *p : vector3(0, 0, 0); // ustawienie współrzędnych, bo do TGroundNode nie ma dostępu
bCommand = false; // komenda wysłana bCommand = false; // komenda wysłana
OnSent = NULL; OnSent = NULL;
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
TMemCell::~TMemCell()
{
SafeDeleteArray(szText);
}
#endif
void TMemCell::Init() void TMemCell::Init()
{ {
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
void TMemCell::UpdateValues(char const *szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask)
#else
void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask ) void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask )
#endif
{ {
if (CheckMask & update_memadd) if (CheckMask & update_memadd)
{ // dodawanie wartości { // dodawanie wartości
if( TestFlag( CheckMask, update_memstring ) ) if( TestFlag( CheckMask, update_memstring ) )
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
strcat( szText, szNewText );
#else
szText += szNewText; szText += szNewText;
#endif
if (TestFlag(CheckMask, update_memval1)) if (TestFlag(CheckMask, update_memval1))
fValue1 += fNewValue1; fValue1 += fNewValue1;
if (TestFlag(CheckMask, update_memval2)) if (TestFlag(CheckMask, update_memval2))
@@ -67,11 +50,7 @@ void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValu
else else
{ {
if( TestFlag( CheckMask, update_memstring ) ) if( TestFlag( CheckMask, update_memstring ) )
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
strcpy( szText, szNewText );
#else
szText = szNewText; szText = szNewText;
#endif
if (TestFlag(CheckMask, update_memval1)) if (TestFlag(CheckMask, update_memval1))
fValue1 = fNewValue1; fValue1 = fNewValue1;
if (TestFlag(CheckMask, update_memval2)) if (TestFlag(CheckMask, update_memval2))
@@ -83,56 +62,32 @@ void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValu
TCommandType TMemCell::CommandCheck() TCommandType TMemCell::CommandCheck()
{ // rozpoznanie komendy { // rozpoznanie komendy
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
if (strcmp(szText, "SetVelocity") == 0) // najpopularniejsze
#else
if( szText == "SetVelocity" ) // najpopularniejsze if( szText == "SetVelocity" ) // najpopularniejsze
#endif
{ {
eCommand = cm_SetVelocity; eCommand = cm_SetVelocity;
bCommand = false; // ta komenda nie jest wysyłana bCommand = false; // ta komenda nie jest wysyłana
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
else if( strcmp( szText, "ShuntVelocity" ) == 0 ) // w tarczach manewrowych
#else
else if( szText == "ShuntVelocity" ) // w tarczach manewrowych else if( szText == "ShuntVelocity" ) // w tarczach manewrowych
#endif
{ {
eCommand = cm_ShuntVelocity; eCommand = cm_ShuntVelocity;
bCommand = false; // ta komenda nie jest wysyłana bCommand = false; // ta komenda nie jest wysyłana
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
else if( strcmp( szText, "Change_direction" ) == 0 ) // zdarza się
#else
else if( szText == "Change_direction" ) // zdarza się else if( szText == "Change_direction" ) // zdarza się
#endif
{ {
eCommand = cm_ChangeDirection; eCommand = cm_ChangeDirection;
bCommand = true; // do wysłania bCommand = true; // do wysłania
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
else if( strcmp( szText, "OutsideStation" ) == 0 ) // zdarza się
#else
else if( szText == "OutsideStation" ) // zdarza się else if( szText == "OutsideStation" ) // zdarza się
#endif
{ {
eCommand = cm_OutsideStation; eCommand = cm_OutsideStation;
bCommand = false; // tego nie powinno być w komórce bCommand = false; // tego nie powinno być w komórce
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
else if( strncmp( szText, "PassengerStopPoint:", 19 ) == 0 ) // porównanie początków
#else
else if( szText.compare( 0, 19, "PassengerStopPoint:" ) == 0 ) // porównanie początków else if( szText.compare( 0, 19, "PassengerStopPoint:" ) == 0 ) // porównanie początków
#endif
{ {
eCommand = cm_PassengerStopPoint; eCommand = cm_PassengerStopPoint;
bCommand = false; // tego nie powinno być w komórce bCommand = false; // tego nie powinno być w komórce
} }
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
else if( strcmp( szText, "SetProximityVelocity" ) == 0 ) // nie powinno tego być
#else
else if( szText == "SetProximityVelocity" ) // nie powinno tego być else if( szText == "SetProximityVelocity" ) // nie powinno tego być
#endif
{ {
eCommand = cm_SetProximityVelocity; eCommand = cm_SetProximityVelocity;
bCommand = false; // ta komenda nie jest wysyłana bCommand = false; // ta komenda nie jest wysyłana
@@ -149,14 +104,7 @@ bool TMemCell::Load(cParser *parser)
{ {
std::string token; std::string token;
parser->getTokens(1, false); // case sensitive parser->getTokens(1, false); // case sensitive
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
*parser >> token;
SafeDeleteArray(szText);
szText = new char[256]; // musi być bufor do łączenia tekstów
strcpy(szText, token.c_str());
#else
*parser >> szText; *parser >> szText;
#endif
parser->getTokens( 2, false ); parser->getTokens( 2, false );
*parser *parser
>> fValue1 >> fValue1
@@ -179,32 +127,6 @@ void TMemCell::PutCommand(TController *Mech, vector3 *Loc)
Mech->PutCommand(szText, fValue1, fValue2, Loc); Mech->PutCommand(szText, fValue1, fValue2, Loc);
} }
bool TMemCell::Compare(char const *szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask)
{ // porównanie zawartości komórki pamięci z podanymi wartościami
if (TestFlag(CheckMask, conditional_memstring))
{ // porównać teksty
std::string
match( szTestText );
auto range = match.find( '*' );
if( range != std::string::npos ) {
// compare string parts
if( 0 != szText.compare( 0, range, match, 0, range ) ) {
return false;
}
}
else {
// compare full strings
if( szText != match ) {
return false;
}
}
}
// tekst zgodny, porównać resztę
return ((!TestFlag(CheckMask, conditional_memval1) || (fValue1 == fTestValue1)) &&
(!TestFlag(CheckMask, conditional_memval2) || (fValue2 == fTestValue2)));
};
#ifndef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
bool TMemCell::Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask ) { bool TMemCell::Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask ) {
// porównanie zawartości komórki pamięci z podanymi wartościami // porównanie zawartości komórki pamięci z podanymi wartościami
if( TestFlag( CheckMask, conditional_memstring ) ) { if( TestFlag( CheckMask, conditional_memstring ) ) {
@@ -224,10 +146,9 @@ bool TMemCell::Compare( std::string const &szTestText, double const fTestValue1,
} }
} }
// tekst zgodny, porównać resztę // tekst zgodny, porównać resztę
return ( ( !TestFlag( CheckMask, conditional_memval1 ) || ( fValue1 == fTestValue1 ) ) && return ( ( !TestFlag( CheckMask, conditional_memval1 ) || ( fValue1 == fTestValue1 ) )
( !TestFlag( CheckMask, conditional_memval2 ) || ( fValue2 == fTestValue2 ) ) ); && ( !TestFlag( CheckMask, conditional_memval2 ) || ( fValue2 == fTestValue2 ) ) );
}; };
#endif
bool TMemCell::Render() bool TMemCell::Render()
{ {

View File

@@ -7,56 +7,31 @@ obtain one at
http://mozilla.org/MPL/2.0/. http://mozilla.org/MPL/2.0/.
*/ */
#ifndef MemCellH #pragma once
#define MemCellH
#include "Classes.h" #include "Classes.h"
#include "dumb3d.h" #include "dumb3d.h"
using namespace Math3D;
using namespace std;
class TMemCell class TMemCell
{ {
private: private:
vector3 vPosition; Math3D::vector3 vPosition;
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
char *szText;
#else
std::string szText; std::string szText;
#endif
double fValue1; double fValue1;
double fValue2; double fValue2;
TCommandType eCommand; TCommandType eCommand;
bool bCommand; // czy zawiera komendę dla zatrzymanego AI bool bCommand; // czy zawiera komendę dla zatrzymanego AI
TEvent *OnSent; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład TEvent *OnSent; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład
public: public:
string std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac TMemCell( Math3D::vector3 *p );
TMemCell(vector3 *p);
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
~TMemCell();
#endif
void Init(); void Init();
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
void UpdateValues( char const *szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask );
#else
void UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask ); void UpdateValues( std::string const &szNewText, double const fNewValue1, double const fNewValue2, int const CheckMask );
#endif
bool Load(cParser *parser); bool Load(cParser *parser);
void PutCommand(TController *Mech, vector3 *Loc); void PutCommand( TController *Mech, Math3D::vector3 *Loc );
bool Compare( char const *szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask );
#ifndef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
bool Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask ); bool Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask );
#endif
bool Render(); bool Render();
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
inline char * Text()
{
return szText;
};
#else
inline std::string const &Text() { return szText; } inline std::string const &Text() { return szText; }
#endif
inline double Value1() inline double Value1()
{ {
return fValue1; return fValue1;
@@ -65,7 +40,7 @@ class TMemCell
{ {
return fValue2; return fValue2;
}; };
inline vector3 Position() inline Math3D::vector3 Position()
{ {
return vPosition; return vPosition;
}; };
@@ -84,4 +59,3 @@ class TMemCell
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif

View File

@@ -317,15 +317,21 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
} }
std::string discard; std::string discard;
parser.getTokens(13, false); parser.getTokens(13, false);
parser >> fNearAttenStart >> discard >> fNearAttenEnd >> discard >> bUseNearAtten >> parser
discard >> iFarAttenDecay >> discard >> fFarDecayRadius >> discard >> >> fNearAttenStart
fCosFalloffAngle // kąt liczony dla średnicy, a nie promienia >> discard >> fNearAttenEnd
>> discard >> bUseNearAtten
>> discard >> iFarAttenDecay
>> discard >> fFarDecayRadius
>> discard >> fCosFalloffAngle // kąt liczony dla średnicy, a nie promienia
>> discard >> fCosHotspotAngle; // kąt liczony dla średnicy, a nie promienia >> discard >> fCosHotspotAngle; // kąt liczony dla średnicy, a nie promienia
fCosFalloffAngle = cos(DegToRad(0.5 * fCosFalloffAngle)); fCosFalloffAngle = std::cos( DegToRad( 0.5f * fCosFalloffAngle ) );
fCosHotspotAngle = cos(DegToRad(0.5 * fCosHotspotAngle)); fCosHotspotAngle = std::cos( DegToRad( 0.5f * fCosHotspotAngle ) );
iNumVerts = 1; iNumVerts = 1;
iFlags |= 0x4010; // rysowane w cyklu nieprzezroczystych, macierz musi /*
// zostać bez zmiany iFlags |= 0x4010; // rysowane w cyklu nieprzezroczystych, macierz musi zostać bez zmiany
*/
iFlags |= 0x4030; // drawn both in solid (light point) and transparent (light glare) phases
} }
else if (eType < TP_ROTATOR) else if (eType < TP_ROTATOR)
{ {
@@ -637,91 +643,8 @@ float8 *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls)
}; };
void TSubModel::DisplayLists() void TSubModel::DisplayLists()
{ // utworznie po jednej skompilowanej liście dla {
// każdego submodelu return;
if (Global::bUseVBO)
return; // Ra: przy VBO to się nie przyda
// iFlags|=0x4000; //wyłączenie przeliczania wierzchołków, bo nie są zachowane
if (eType < TP_ROTATOR)
{
if (iNumVerts > 0)
{
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
glColor3fv(f4Diffuse); // McZapkie-240702: zamiast ub
#ifdef USE_VERTEX_ARRAYS
// ShaXbee-121209: przekazywanie wierzcholkow hurtem
glVertexPointer(3, GL_DOUBLE, sizeof(GLVERTEX), &Vertices[0].Point.x);
glNormalPointer(GL_DOUBLE, sizeof(GLVERTEX), &Vertices[0].Normal.x);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLVERTEX), &Vertices[0].tu);
glDrawArrays(eType, 0, iNumVerts);
#else
glBegin(eType);
for (int i = 0; i < iNumVerts; i++)
{
/*
glNormal3dv(&Vertices[i].Normal.x);
glTexCoord2f(Vertices[i].tu,Vertices[i].tv);
glVertex3dv(&Vertices[i].Point.x);
*/
glNormal3fv(&Vertices[i].Normal.x);
glTexCoord2f(Vertices[i].tu, Vertices[i].tv);
glVertex3fv(&Vertices[i].Point.x);
};
glEnd();
#endif
glEndList();
}
}
else if (eType == TP_FREESPOTLIGHT)
{
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
GfxRenderer.Bind(0);
// if (eType==smt_FreeSpotLight)
// {
// if (iFarAttenDecay==0)
// glColor3f(Diffuse[0],Diffuse[1],Diffuse[2]);
// }
// else
// TODO: poprawic zeby dzialalo
// glColor3f(f4Diffuse[0],f4Diffuse[1],f4Diffuse[2]);
glColorMaterial(GL_FRONT, GL_EMISSION);
glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie blendowaly
glBegin(GL_POINTS);
glVertex3f( 0.0f, 0.0f, -0.05f ); // shift point towards the viewer, to avoid z-fighting with the light polygons
glEnd();
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
glEndList();
}
else if (eType == TP_STARS)
{ // punkty świecące dookólnie
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
GfxRenderer.Bind(0); // tekstury nie ma
glColorMaterial(GL_FRONT, GL_EMISSION);
// glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie blendowaly
glBegin(GL_POINTS);
for (int i = 0; i < iNumVerts; i++)
{
glColor3f(Vertices[i].Normal.x, Vertices[i].Normal.y, Vertices[i].Normal.z);
// glVertex3dv(&Vertices[i].Point.x);
glVertex3fv(&Vertices[i].Point.x);
};
glEnd();
// glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
glEndList();
}
// SafeDeleteArray(Vertices); //przy VBO muszą zostać do załadowania całego
// modelu
if (Child)
Child->DisplayLists();
if (Next)
Next->DisplayLists();
}; };
void TSubModel::InitialRotate(bool doit) void TSubModel::InitialRotate(bool doit)
@@ -976,22 +899,22 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
m = glm::rotate(m, glm::radians(v_Angles.z), glm::vec3(0.0f, 0.0f, 1.0f)); m = glm::rotate(m, glm::radians(v_Angles.z), glm::vec3(0.0f, 0.0f, 1.0f));
break; break;
case at_SecondsJump: // sekundy z przeskokiem case at_SecondsJump: // sekundy z przeskokiem
m = glm::rotate(m, glm::radians((float)floor(GlobalTime->mr) * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(Simulation::Time.data().wSecond * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_MinutesJump: // minuty z przeskokiem case at_MinutesJump: // minuty z przeskokiem
m = glm::rotate(m, glm::radians(GlobalTime->mm * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(Simulation::Time.data().wMinute * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_HoursJump: // godziny skokowo 12h/360° case at_HoursJump: // godziny skokowo 12h/360°
m = glm::rotate(m, glm::radians(GlobalTime->hh * 30.0f * 0.5f), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(Simulation::Time.data().wHour * 30.0f * 0.5f), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_Hours24Jump: // godziny skokowo 24h/360° case at_Hours24Jump: // godziny skokowo 24h/360°
m = glm::rotate(m, glm::radians(GlobalTime->hh * 15.0f * 0.25f), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(Simulation::Time.data().wHour * 15.0f * 0.25f), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_Seconds: // sekundy płynnie case at_Seconds: // sekundy płynnie
m = glm::rotate(m, glm::radians((float)GlobalTime->mr * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians((float)Simulation::Time.second() * 6.0f), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_Minutes: // minuty płynnie case at_Minutes: // minuty płynnie
m = glm::rotate(m, glm::radians((float)(GlobalTime->mm * 6.0 + GlobalTime->mr * 0.1)), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(Simulation::Time.data().wMinute * 6.0f + (float)Simulation::Time.second() * 0.1f), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_Hours: // godziny płynnie 12h/360° case at_Hours: // godziny płynnie 12h/360°
// glRotatef(GlobalTime->hh*30.0+GlobalTime->mm*0.5+GlobalTime->mr/120.0,0.0,1.0,0.0); // glRotatef(GlobalTime->hh*30.0+GlobalTime->mm*0.5+GlobalTime->mr/120.0,0.0,1.0,0.0);
@@ -1007,18 +930,20 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
matrix4x4 mat; // potrzebujemy współrzędne przesunięcia środka układu matrix4x4 mat; // potrzebujemy współrzędne przesunięcia środka układu
// współrzędnych submodelu // współrzędnych submodelu
glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray()); // pobranie aktualnej matrycy glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray()); // pobranie aktualnej matrycy
float3 gdzie = float3(mat[3][0], mat[3][1],
mat[3][2]); // początek układu współrzędnych submodelu względem kamery matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
float3 gdzie = float3(mat[3][0], mat[3][1], mat[3][2]); // początek układu współrzędnych submodelu względem kamery
glLoadIdentity(); // macierz jedynkowa glLoadIdentity(); // macierz jedynkowa
glTranslatef(gdzie.x, gdzie.y, gdzie.z); // początek układu zostaje bez glTranslatef(gdzie.x, gdzie.y, gdzie.z); // początek układu zostaje bez
// zmian // zmian
glRotated(atan2(gdzie.x, gdzie.z) * 180.0 / M_PI, 0.0, 1.0, glRotated(atan2(gdzie.x, gdzie.z) * 180.0 / M_PI, 0.0, 1.0,
0.0); // jedynie obracamy w pionie o kąt 0.0); // jedynie obracamy w pionie o kąt
*/ //m7todo: restore */
//m7todo: restore
} }
break; break;
case at_Wind: // ruch pod wpływem wiatru (wiatr będziemy liczyć potem...) case at_Wind: // ruch pod wpływem wiatru (wiatr będziemy liczyć potem...)
m = glm::rotate(m, glm::radians(1.5f * (float)sin(M_PI * GlobalTime->mr / 6.0)), glm::vec3(0.0f, 1.0f, 0.0f)); m = glm::rotate(m, glm::radians(1.5f * (float)sin(M_PI * Simulation::Time.second() / 6.0)), glm::vec3(0.0f, 1.0f, 0.0f));
break; break;
case at_Sky: // animacja nieba case at_Sky: // animacja nieba
m = glm::rotate(m, glm::radians((float)Global::fLatitudeDeg), glm::vec3(0.0f, 1.0f, 0.0f)); // ustawienie osi OY na północ m = glm::rotate(m, glm::radians((float)Global::fLatitudeDeg), glm::vec3(0.0f, 1.0f, 0.0f)); // ustawienie osi OY na północ
@@ -1052,6 +977,7 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
} }
}; };
#ifdef EU07_USE_OLD_RENDERCODE
void TSubModel::RenderDL() void TSubModel::RenderDL()
{ // główna procedura renderowania przez DL { // główna procedura renderowania przez DL
return; return;
@@ -1275,8 +1201,11 @@ void TSubModel::RenderVBO(glm::mat4 m)
} }
else if (eType == TP_FREESPOTLIGHT) else if (eType == TP_FREESPOTLIGHT)
{ // wersja VBO { // wersja VBO
/*
matrix4x4 mat; // macierz opisuje układ renderowania względem kamery matrix4x4 mat; // macierz opisuje układ renderowania względem kamery
glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray()); glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray());
*/
matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
// kąt między kierunkiem światła a współrzędnymi kamery // kąt między kierunkiem światła a współrzędnymi kamery
vector3 gdzie = mat * vector3(0, 0, 0); // pozycja punktu świecącego względem kamery vector3 gdzie = mat * vector3(0, 0, 0); // pozycja punktu świecącego względem kamery
fCosViewAngle = DotProduct(Normalize(mat * vector3(0, 0, 1) - gdzie), Normalize(gdzie)); fCosViewAngle = DotProduct(Normalize(mat * vector3(0, 0, 1) - gdzie), Normalize(gdzie));
@@ -1398,7 +1327,7 @@ void TSubModel::RenderAlphaVBO(glm::mat4 m)
if (iAlpha & iFlags & 0x2F000000) if (iAlpha & iFlags & 0x2F000000)
Next->RenderAlphaVBO(m); Next->RenderAlphaVBO(m);
}; // RaRenderAlpha }; // RaRenderAlpha
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TSubModel::RaArrayFill(CVertNormTex *Vert) void TSubModel::RaArrayFill(CVertNormTex *Vert)
@@ -1956,8 +1885,6 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
pName = ""; pName = "";
if (iTexture > 0) if (iTexture > 0)
{ // obsługa stałej tekstury { // obsługa stałej tekstury
// TextureID=TTexturesManager::GetTextureID(t->String(TextureID));
// asTexture=AnsiString(t->String(iTexture));
pTexture = t->at(iTexture); pTexture = t->at(iTexture);
if (pTexture.find_last_of("/\\") == std::string::npos) if (pTexture.find_last_of("/\\") == std::string::npos)
pTexture.insert(0, Global::asCurrentTexturePath); pTexture.insert(0, Global::asCurrentTexturePath);
@@ -1966,9 +1893,17 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
} }
else else
TextureID = iTexture; TextureID = iTexture;
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem
// tablic) if( (eType == TP_FREESPOTLIGHT) && (iFlags & 0x10)) {
// we've added light glare which needs to be rendered during transparent phase,
// but models converted to e3d before addition won't have the render flag set correctly for this
// so as a workaround we're doing it here manually
iFlags |= 0x20;
}
iFlags &= ~0x0200; // wczytano z pliku binarnego (nie jest właścicielem tablic)
iVboPtr = tVboPtr; iVboPtr = tVboPtr;
Vertices = v + iVboPtr; Vertices = v + iVboPtr;
// if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie // if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie
@@ -2074,8 +2009,6 @@ void TModel3d::Init()
Root->AdjustDist(); // aktualizacja odległości faz LoD, zależnie od Root->AdjustDist(); // aktualizacja odległości faz LoD, zależnie od
// rozdzielczości pionowej oraz multisamplingu // rozdzielczości pionowej oraz multisamplingu
*/ */
if (Global::bUseVBO)
{
if (!m_pVNT) // jeśli nie ma jeszcze tablicy (wczytano z pliku if (!m_pVNT) // jeśli nie ma jeszcze tablicy (wczytano z pliku
// tekstowego) // tekstowego)
{ // tworzenie tymczasowej tablicy z wierzchołkami całego modelu { // tworzenie tymczasowej tablicy z wierzchołkami całego modelu
@@ -2085,11 +2018,6 @@ void TModel3d::Init()
} }
else else
BuildVBOs(false); // tworzenie VBO bez usuwania tablicy z pamięci BuildVBOs(false); // tworzenie VBO bez usuwania tablicy z pamięci
}
else
{ // przygotowanie skompilowanych siatek dla DisplayLists
Root->DisplayLists(); // tworzenie skompilowanej listy dla submodelu
}
// if (Root->TextureID) //o ile ma teksturę // if (Root->TextureID) //o ile ma teksturę
// Root->iFlags|=0x80; //konieczność ustawienia tekstury // Root->iFlags|=0x80; //konieczność ustawienia tekstury
} }
@@ -2122,7 +2050,7 @@ void TModel3d::RenderAlpha(double fSquareDistance, texture_manager::size_type *R
Root->RenderAlphaDL(); Root->RenderAlphaDL();
} }
}; };
#endif
void TModel3d::RaRender(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId, int iAlpha) void TModel3d::RaRender(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
{ // renderowanie specjalne, np. kabiny { // renderowanie specjalne, np. kabiny
iAlpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste iAlpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste
@@ -2166,7 +2094,7 @@ void TModel3d::RaRenderAlpha(double fSquareDistance, texture_manager::size_type
} }
} }
}; };
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów // 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2205,7 +2133,7 @@ void TModel3d::RenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manager:
Root->RenderAlphaDL(); Root->RenderAlphaDL();
glPopMatrix(); glPopMatrix();
}; };
#endif
void TModel3d::RaRender(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId, int iAlpha) void TModel3d::RaRender(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
{ // nieprzezroczyste, VBO { // nieprzezroczyste, VBO
glPushMatrix(); glPushMatrix();
@@ -2261,7 +2189,7 @@ void TModel3d::RaRenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manage
} }
glPopMatrix(); glPopMatrix();
}; };
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 2012-02 funkcje do tworzenia terenu z E3D // 2012-02 funkcje do tworzenia terenu z E3D
@@ -2313,9 +2241,8 @@ void TModel3d::TerrainRenderVBO(int n)
TSubModel *r = Root; TSubModel *r = Root;
while (r) while (r)
{ {
if (r->iVisible == if (r->iVisible == n) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
n) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false) GfxRenderer.Render(r); // sub kolejne (Next) się nie wyrenderują
r->RenderVBO(glm::make_mat4(mv)); // sub kolejne (Next) się nie wyrenderują
r = r->NextGet(); r = r->NextGet();
} }
EndVBO(); EndVBO();

View File

@@ -182,8 +182,7 @@ private:
int iFarAttenDecay; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R) int iFarAttenDecay; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R)
float fFarDecayRadius; // normalizacja j.w. float fFarDecayRadius; // normalizacja j.w.
float fCosFalloffAngle; // cosinus kąta stożka pod którym widać światło float fCosFalloffAngle; // cosinus kąta stożka pod którym widać światło
float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
// światła
float fCosViewAngle; // cos kata pod jakim sie teraz patrzy float fCosViewAngle; // cos kata pod jakim sie teraz patrzy
TSubModel *Next; TSubModel *Next;
@@ -256,10 +255,12 @@ public:
void SetRotateIK1(float3 vNewAngles); void SetRotateIK1(float3 vNewAngles);
TSubModel * GetFromName(std::string const &search, bool i = true); TSubModel * GetFromName(std::string const &search, bool i = true);
TSubModel * GetFromName(char const *search, bool i = true); TSubModel * GetFromName(char const *search, bool i = true);
#ifdef EU07_USE_OLD_RENDERCODE
void RenderDL(); void RenderDL();
void RenderAlphaDL(); void RenderAlphaDL();
void RenderVBO(glm::mat4 m); void RenderVBO();
void RenderAlphaVBO(glm::mat4 m); void RenderAlphaVBO();
#endif
// inline matrix4x4* GetMatrix() {return dMatrix;}; // inline matrix4x4* GetMatrix() {return dMatrix;};
inline float4x4 * GetMatrix() inline float4x4 * GetMatrix()
{ {

176
Names.cpp
View File

@@ -11,179 +11,3 @@ http://mozilla.org/MPL/2.0/.
#include "Names.h" #include "Names.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/*
Moduł zarządzający plikami oraz wyszukiwaniem obiektów wg nazw.
1. Ma przydzielony z góry (EU07.INI) obszar pamięci (rzędu 16MB).
2. W przypadku przepełnienia dostępnej pamięci wystąpi błąd wczytywania.
3. Obszar ten będzie zużywany na rekordy obiektów oraz ciągi tekstowe z nazwami.
4. Rekordy będą sortowane w ramach typu (tekstury, dźwięki, modele, node, eventy).
5. Pierwszy etap wyszukiwania to 5 bitów z pierwszego bajtu i 3 z drugiego (256).
6. Dla plików istnieje możliwość wczytania ich w innym terminie.
7. Możliwość wczytania plików w oddzielnym watku (np. tekstur).
Obsługiwane pliki:
1. Tekstury, można wczytywać później, rekord przechowuje numer podany przez kartę graficzną.
2. Dźwięki, można wczytać później.
3. Modele, można wczytać później o ile nie mają animacji eventami i nie dotyczą pojazdów.
Obiekty sortowane wg nazw, można dodawać i usuwać komórki scenerii:
4. Tory, drogi, rzeki - wyszukiwanie w celu sprawdzenia zajetości.
5. Eventy - wyszukiwane przy zewnętrznym wywołaniu oraz podczas wczytywania.
6. Pojazdy - wyszukiwane w celu wysyłania komend.
7. Egzemplarze modeli animowanych - wyszukiwanie w celu połączenia z animacjami.
*/
#ifdef EU07_USE_OLD_TNAMES_CLASS
void ItemRecord::TreeAdd(ItemRecord *r, int c)
{ // dodanie rekordu do drzewa - ustalenie w której gałęzi
// zapisać w (iFlags) ile znaków jest zgodnych z nadrzędnym, żeby nie sprawdzać wszystkich od
// zera
if ((cName[c] && r->cName[c]) ? cName[c] == r->cName[c] : false)
TreeAdd(r, c + 1); // ustawić wg kolejnego znaku, chyba że zero
else if ((unsigned char)(cName[c]) < (unsigned char)(r->cName[c]))
{ // zero jest najmniejsze - doczepiamy jako (rNext)
if (!rNext)
rNext = r;
else
rNext->TreeAdd(r, 0); // doczepić do tej gałęzi
}
else
{
if (!rPrev)
rPrev = r;
else
rPrev->TreeAdd(r, 0); // doczepić do tej gałęzi
}
};
void ItemRecord::ListGet(ItemRecord *r, int *&n)
{ // rekurencyjne wypełnianie posortowanej listy na podstawie drzewa
if (rPrev)
rPrev->ListGet(r, n); // dodanie wszystkich wcześniejszych
*n++ = this - r; // dodanie swojego indeksu do tabeli
if (rNext)
rNext->ListGet(r, n); // dodanie wszystkich późniejszych
};
void * ItemRecord::TreeFind(const char *n)
{ // wyszukanie ciągu (n)
ItemRecord *r = TreeFindRecord(n);
return r ? r->pData : NULL;
};
ItemRecord * ItemRecord::TreeFindRecord(const char *n)
{ // wyszukanie ciągu (n)
ItemRecord *r = this; //żeby nie robić rekurencji
int i = 0;
do
{
if (!n[i])
if (!r->cName[i])
return r; // znaleziony
if (n[i] == r->cName[i])
++i; // porównać kolejny znak
else if ((unsigned char)(n[i]) < (unsigned char)(r->cName[i]))
{
i = 0; // porównywać od nowa
r = r->rPrev; // wcześniejsza gałąź drzewa
}
else
{
i = 0; // porównywać od nowa
r = r->rNext; // późniejsza gałąź drzewa
}
} while (r);
return NULL;
};
TNames::TNames()
{ // tworzenie bufora
iSize = 16 * 1024 * 1024; // rozmiar bufora w bajtach
cBuffer = new char[iSize];
ZeroMemory(cBuffer, iSize); // nie trzymać jakiś starych śmieci
rRecords = (ItemRecord *)cBuffer;
cLast = cBuffer + iSize; // bajt za buforem
iLast = -1;
ZeroMemory(rTypes, 20 * sizeof(ItemRecord *));
};
TNames::~TNames() {
delete[] cBuffer;
}
int TNames::Add(int t, const char *n)
{ // dodanie obiektu typu (t) o nazwie (n)
int len = strlen(n) + 1; // ze znacznikiem końca
cLast -= len; // rezerwacja miejsca
memcpy(cLast, n, len); // przekopiowanie tekstu do bufora
// cLast[len-1]='\0';
rRecords[++iLast].cName = cLast; // połączenie nazwy z rekordem
rRecords[iLast].iFlags = t;
if (!rTypes[t])
rTypes[t] = rRecords + iLast; // korzeń drzewa, bo nie było wcześniej
else
rTypes[t]->TreeAdd(rRecords + iLast, 0); // doczepienie jako gałąź
// rTypes[t]=Sort(t); //sortowanie uruchamiać ręcznie
if ((iLast & 0x3F) == 0) // nie za często, bo sortowania zajmą więcej czasu niż wyszukiwania
Sort(t); // optymalizacja drzewa co jakiś czas
return iLast;
}
int TNames::Add(int t, const char *n, void *d)
{
int i = Add(t, n);
rRecords[iLast].pData = d;
return i;
};
bool TNames::Update(int t, const char *n, void *d)
{ // dodanie jeśli nie ma, wymiana (d), gdy jest
ItemRecord *r = FindRecord(t, n); // najpierw sprawdzić, czy już jest
if (r)
{ // przy zdublowaniu nazwy podmieniać w drzewku na późniejszy
r->pData = d;
return true; // duplikat
}
// Add(t,n,d); //nazwa unikalna
return false; // został dodany nowy
};
ItemRecord * TNames::TreeSet(int *n, int d, int u)
{ // rekurencyjne wypełnianie drzewa pozycjami od (d) do (u)
if (d == u)
{
rRecords[n[d]].rPrev = rRecords[n[d]].rNext = NULL;
return rRecords + n[d]; // tej gałęzi nie ma
}
else if (d > u)
return NULL;
int p = (u + d) >> 1; // połowa
rRecords[n[p]].rPrev = TreeSet(n, d, p - 1); // zapisanie wcześniejszych gałęzi
rRecords[n[p]].rNext = TreeSet(n, p + 1, u); // zapisanie późniejszych gałęzi
return rRecords + n[p];
};
void TNames::Sort(int t)
{ // przebudowa drzewa typu (t), zwraca wierzchołek drzewa
if (iLast < 3)
return; // jak jest mało, to nie ma sensu sortować
if (rTypes[t]) // jeśli jest jakiś rekord danego typu
{
int *r = new int[iLast + 1]; // robocza tablica indeksów - numery posortowanych rekordów
int *q = r; // wskaźnik roboczy, przekazywany przez referencję
rTypes[t]->ListGet(rRecords, q); // drzewo jest już posortowane - zamienić je na listę
rTypes[t] = TreeSet(r, 0, (q - r) - 1);
delete[] r;
}
return;
};
ItemRecord * TNames::FindRecord(const int t, const char *n)
{ // poszukiwanie rekordu w celu np. zmiany wskaźnika
return rTypes[t] ? rTypes[t]->TreeFindRecord(n) : NULL;
};
#endif

82
Names.h
View File

@@ -1,4 +1,3 @@
#pragma once
/* /*
This Source Code Form is subject to the This Source Code Form is subject to the
terms of the Mozilla Public License, v. terms of the Mozilla Public License, v.
@@ -8,12 +7,12 @@ obtain one at
http://mozilla.org/MPL/2.0/. http://mozilla.org/MPL/2.0/.
*/ */
#pragma once
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
#ifndef EU07_USE_OLD_TNAMES_CLASS template <typename _Type>
template <typename _Pointer>
class TNames { class TNames {
public: public:
@@ -27,7 +26,7 @@ public:
// methods: // methods:
// dodanie obiektu z wskaźnikiem. updates data field if the object already exists. returns true for insertion, false for update // dodanie obiektu z wskaźnikiem. updates data field if the object already exists. returns true for insertion, false for update
bool bool
Add( int const Type, std::string const &Name, _Pointer Data ) { Add( int const Type, std::string const &Name, _Type Data ) {
auto lookup = find_map( Type ).emplace( Name, Data ); auto lookup = find_map( Type ).emplace( Name, Data );
if( lookup.second == false ) { if( lookup.second == false ) {
@@ -41,7 +40,7 @@ public:
} }
} }
// returns pointer associated with provided label, or nullptr if there's no match // returns pointer associated with provided label, or nullptr if there's no match
_Pointer _Type
Find( int const Type, std::string const &Name ) { Find( int const Type, std::string const &Name ) {
auto const &map = find_map( Type ); auto const &map = find_map( Type );
@@ -52,78 +51,17 @@ public:
private: private:
// types: // types:
typedef std::unordered_map<std::string, _Pointer> pointer_map; typedef std::unordered_map<std::string, _Type> type_map;
typedef std::unordered_map<int, pointer_map> pointermap_map; typedef std::unordered_map<int, type_map> typemap_map;
// methods: // methods:
// returns database stored with specified type key; creates new database if needed. // returns database stored with specified type key; creates new database if needed.
pointer_map & type_map &
find_map( int const Type ) { find_map( int const Type ) {
return m_maps.emplace( Type, pointer_map() ).first->second; return m_maps.emplace( Type, type_map() ).first->second;
} }
// members: // members:
pointermap_map m_maps; // list of pointer maps of types specified so far typemap_map m_maps; // list of object maps of types specified so far
}; };
#else
//---------------------------------------------------------------------------
class ItemRecord
{ // rekord opisujący obiekt; raz utworzony nie przemieszcza się
// rozmiar rekordu można zmienić w razie potrzeby
public:
char *cName; // wskaźnik do nazwy umieszczonej w buforze
int iFlags; // flagi bitowe
ItemRecord *rPrev, *rNext; // posortowane drzewo (przebudowywane w razie potrzeby)
union
{
void *pData; // wskaźnik do obiektu
int iData; // albo numer obiektu (tekstury)
unsigned int uData;
};
// typedef
void ListGet(ItemRecord *r, int *&n);
void TreeAdd(ItemRecord *r, int c);
template <typename TOut> inline TOut *DataGet()
{
return (TOut *)pData;
};
template <typename TOut> inline void DataSet(TOut *x)
{
pData = (void *)x;
};
void * TreeFind(const char *n);
ItemRecord * TreeFindRecord(const char *n);
};
class TNames
{
public:
int iSize; // rozmiar bufora
char *cBuffer; // bufor dla rekordów (na początku) i nazw (na końcu)
ItemRecord *rRecords; // rekordy na początku bufora
char *cLast; // ostatni użyty bajt na nazwy
ItemRecord *rTypes[20]; // rożne typy obiektów (początek drzewa)
int iLast; // ostatnio użyty rekord
public:
TNames();
~TNames();
int Add(int t, const char *n); // dodanie obiektu typu (t)
int Add(int t, const char *n, void *d); // dodanie obiektu z wskaźnikiem
int Add(int t, const char *n, int d); // dodanie obiektu z numerem
bool Update(int t, const char *n, void *d); // dodanie jeśli nie ma, wymiana (d), gdy jest
void TreeSet();
ItemRecord * TreeSet(int *n, int d, int u);
void Sort(int t); // przebudowa drzewa typu (t)
ItemRecord * Item(int n); // rekord o numerze (n)
inline void *Find(const int t, const char *n)
{
return rTypes[t] ? rTypes[t]->TreeFind(n) : NULL;
};
ItemRecord * FindRecord(const int t, const char *n);
// template <typename TOut> inline TOut* Find(const int t,const char *n)
//{return (TOut*)(rTypes[t]->TreeFind(n));};
};
#endif

View File

@@ -307,7 +307,7 @@ void TPythonScreenRenderer::updateTexture()
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
} }
// build texture // build texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData );
#ifdef _PY_INT_MORE_LOG #ifdef _PY_INT_MORE_LOG
GLenum status = glGetError(); GLenum status = glGetError();

View File

@@ -18,7 +18,7 @@ double ResourceManager::_lastReport = 0.0f;
void ResourceManager::Register(Resource *resource) void ResourceManager::Register(Resource *resource)
{ {
_resources.push_back(resource); _resources.emplace_back(resource);
}; };
void ResourceManager::Unregister(Resource *resource) void ResourceManager::Unregister(Resource *resource)

View File

@@ -42,10 +42,12 @@ TSegment::~TSegment()
SafeDeleteArray(fTsBuffer); SafeDeleteArray(fTsBuffer);
}; };
bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1, bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1, double fNewRoll2)
double fNewRoll2)
{ // wersja dla prostego - wyliczanie punktów kontrolnych { // wersja dla prostego - wyliczanie punktów kontrolnych
vector3 dir; vector3 dir;
// NOTE: we're enforcing division also for straight track, to ensure dense enough mesh for per-vertex lighting
/*
if (fNewRoll1 == fNewRoll2) if (fNewRoll1 == fNewRoll2)
{ // faktyczny prosty { // faktyczny prosty
dir = Normalize(NewPoint2 - NewPoint1); // wektor kierunku o długości 1 dir = Normalize(NewPoint2 - NewPoint1); // wektor kierunku o długości 1
@@ -53,10 +55,13 @@ bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, doubl
false); false);
} }
else else
*/
{ // prosty ze zmienną przechyłką musi być segmentowany jak krzywe { // prosty ze zmienną przechyłką musi być segmentowany jak krzywe
dir = (NewPoint2 - NewPoint1) / 3.0; // punkty kontrolne prostego są w 1/3 długości dir = (NewPoint2 - NewPoint1) / 3.0; // punkty kontrolne prostego są w 1/3 długości
return TSegment::Init(NewPoint1, NewPoint1 + dir, NewPoint2 - dir, NewPoint2, fNewStep, return TSegment::Init(
fNewRoll1, fNewRoll2, true); NewPoint1, NewPoint1 + dir,
NewPoint2 - dir, NewPoint2,
fNewStep, fNewRoll1, fNewRoll2, true);
} }
}; };
@@ -113,39 +118,30 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
fStep = fNewStep; fStep = fNewStep;
if (fLength <= 0) if (fLength <= 0)
{ {
ErrorLog("Bad geometry: Length <= 0 in TSegment::Init at " + Where(Point1)); ErrorLog( "Bad geometry (zero length) for spline \"" + pOwner->NameGet() + "\" at " + Where( Point1 ) );
// MessageBox(0,"Length<=0","TSegment::Init",MB_OK); // MessageBox(0,"Length<=0","TSegment::Init",MB_OK);
return false; // zerowe nie mogą być return false; // zerowe nie mogą być
} }
fStoop = atan2((Point2.y - Point1.y), fStoop = atan2((Point2.y - Point1.y),
fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
SafeDeleteArray(fTsBuffer); SafeDeleteArray(fTsBuffer);
/*
if ((bCurve) && (fStep > 0)) if( ( bCurve ) && ( fStep > 0 ) ) {
*/ if( fStep > 0 ) { // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
// we're enforcing sub-division of even straight track, to have dense enough mesh for the spotlight to work with
if( fStep > 0 )
{ // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
double s = 0; double s = 0;
int i = 0; int i = 0;
iSegCount = ceil(fLength / fStep); // potrzebne do VBO iSegCount = ceil( fLength / fStep ); // potrzebne do VBO
// fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału // fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
fTsBuffer = new double[iSegCount + 1]; fTsBuffer = new double[ iSegCount + 1 ];
fTsBuffer[0] = 0; /* TODO : fix fTsBuffer */ fTsBuffer[ 0 ] = 0; /* TODO : fix fTsBuffer */
while (s < fLength) while( s < fLength ) {
{
i++; i++;
s += fStep; s += fStep;
if (s > fLength) if( s > fLength )
s = fLength; s = fLength;
fTsBuffer[i] = GetTFromS(s); fTsBuffer[ i ] = GetTFromS( s );
} }
} }
if (fLength > 500)
{ // tor ma pojemność 40 pojazdów, więc nie może być za długi
ErrorLog("Bad geometry: Length > 500m at " + Where(Point1));
// MessageBox(0,"Length>500","TSegment::Init",MB_OK);
return false;
} }
return true; return true;
} }
@@ -224,7 +220,7 @@ double TSegment::GetTFromS(double s)
// Newton's method failed. If this happens, increase iterations or // Newton's method failed. If this happens, increase iterations or
// tolerance or integration accuracy. // tolerance or integration accuracy.
// return -1; //Ra: tu nigdy nie dojdzie // return -1; //Ra: tu nigdy nie dojdzie
ErrorLog( "Bad geometry: Too many iterations at " + Where( Point1 ) ); ErrorLog( "Bad geometry (shape estimation failed) for spline \"" + pOwner->NameGet() + "\" at " + Where( Point1 ) );
// MessageBox(0,"Too many iterations","GetTFromS",MB_OK); // MessageBox(0,"Too many iterations","GetTFromS",MB_OK);
return fTime; return fTime;
}; };
@@ -405,7 +401,9 @@ void TSegment::RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, doubl
jmm1 * ShapePoints[j].z + m1 * ShapePoints[j + iNumShapePoints].z, tv1); jmm1 * ShapePoints[j].z + m1 * ShapePoints[j + iNumShapePoints].z, tv1);
glVertex3f(pt.x, pt.y, pt.z); // pt nie mamy gdzie zapamiętać? glVertex3f(pt.x, pt.y, pt.z); // pt nie mamy gdzie zapamiętać?
} }
if (p) // jeśli jest wskaźnik do tablicy // BUG: things blow up badly in the following part in 64bit version on baltyk.scn
// TODO: sort this mess out when the time comes to reorganize spline generation
if( p ) // jeśli jest wskaźnik do tablicy
if (*p) if (*p)
if (!j) // to dla pierwszego punktu if (!j) // to dla pierwszego punktu
{ {

View File

@@ -66,6 +66,8 @@ opengl_texture::load() {
fail: fail:
data_state = resource_state::failed; data_state = resource_state::failed;
ErrorLog( "Failed to load texture \"" + name + "\"" ); ErrorLog( "Failed to load texture \"" + name + "\"" );
// NOTE: temporary workaround for texture assignment errors
id = 0;
return; return;
} }
@@ -252,6 +254,7 @@ opengl_texture::load_DDS() {
data_width /= 2; data_width /= 2;
data_height /= 2; data_height /= 2;
--data_mapcount; --data_mapcount;
WriteLog( "Texture size exceeds specified limits, skipping mipmap level" );
}; };
if( data_mapcount <= 0 ) { if( data_mapcount <= 0 ) {
@@ -580,9 +583,9 @@ opengl_texture::create() {
dataheight = std::max( dataheight / 2, 1 ); dataheight = std::max( dataheight / 2, 1 );
} }
else { else {
// uncompressed texture data // uncompressed texture data. have the gfx card do the compression as it sees fit
::glTexImage2D( ::glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA8, GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA,
data_width, data_height, 0, data_width, data_height, 0,
data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[ 0 ] ); data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[ 0 ] );
} }
@@ -676,6 +679,7 @@ opengl_texture::downsize( GLuint const Format ) {
break; break;
} }
WriteLog( "Texture size exceeds specified limits, downsampling data" );
switch( Format ) { switch( Format ) {
case GL_RGB: { downsample< glm::tvec3<std::uint8_t> >( data_width, data_height, data.data() ); break; } case GL_RGB: { downsample< glm::tvec3<std::uint8_t> >( data_width, data_height, data.data() ); break; }
@@ -817,8 +821,9 @@ texture_manager::Bind( texture_manager::size_type const Id ) {
// TODO: do binding in texture object, add support for other types // TODO: do binding in texture object, add support for other types
if( Id != 0 ) { if( Id != 0 ) {
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD #ifndef EU07_DEFERRED_TEXTURE_UPLOAD
::glBindTexture( GL_TEXTURE_2D, Id ); // NOTE: we could bind dedicated 'error' texture here if the id isn't valid
m_activetexture = 0; ::glBindTexture( GL_TEXTURE_2D, Texture(Id).id );
m_activetexture = Texture(Id).id;
#else #else
if( Texture( Id ).bind() == resource_state::good ) { if( Texture( Id ).bind() == resource_state::good ) {
m_activetexture = Id; m_activetexture = Id;

View File

@@ -7,8 +7,7 @@ obtain one at
http://mozilla.org/MPL/2.0/. http://mozilla.org/MPL/2.0/.
*/ */
#ifndef TimerH #pragma once
#define TimerH
namespace Timer namespace Timer
{ {
@@ -36,4 +35,3 @@ void UpdateTimers(bool pause);
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif

139
Track.cpp
View File

@@ -77,7 +77,7 @@ TIsolated::TIsolated()
TIsolated("none", NULL); TIsolated("none", NULL);
}; };
TIsolated::TIsolated(const string &n, TIsolated *i) : TIsolated::TIsolated(std::string const &n, TIsolated *i) :
asName( n ), pNext( i ) asName( n ), pNext( i )
{ {
// utworznie obwodu izolowanego. nothing to do here. // utworznie obwodu izolowanego. nothing to do here.
@@ -96,7 +96,7 @@ TIsolated::~TIsolated(){
*/ */
}; };
TIsolated * TIsolated::Find(const string &n) TIsolated * TIsolated::Find(std::string const &n)
{ // znalezienie obiektu albo utworzenie nowego { // znalezienie obiektu albo utworzenie nowego
TIsolated *p = pRoot; TIsolated *p = pRoot;
while (p) while (p)
@@ -121,13 +121,8 @@ void TIsolated::Modify(int i, TDynamicObject *o)
if (Global::iMultiplayer) // jeśli multiplayer if (Global::iMultiplayer) // jeśli multiplayer
Global::pGround->WyslijString(asName, 10); // wysłanie pakietu o zwolnieniu Global::pGround->WyslijString(asName, 10); // wysłanie pakietu o zwolnieniu
if (pMemCell) // w powiązanej komórce if (pMemCell) // w powiązanej komórce
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
pMemCell->UpdateValues( NULL, 0, int( pMemCell->Value2() ) & ~0xFF,
update_memval2); //"zerujemy" ostatnią wartość
#else
pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) & ~0xFF, pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) & ~0xFF,
update_memval2 ); //"zerujemy" ostatnią wartość update_memval2 ); //"zerujemy" ostatnią wartość
#endif
} }
} }
else else
@@ -140,12 +135,7 @@ void TIsolated::Modify(int i, TDynamicObject *o)
if (Global::iMultiplayer) // jeśli multiplayer if (Global::iMultiplayer) // jeśli multiplayer
Global::pGround->WyslijString(asName, 11); // wysłanie pakietu o zajęciu Global::pGround->WyslijString(asName, 11); // wysłanie pakietu o zajęciu
if (pMemCell) // w powiązanej komórce if (pMemCell) // w powiązanej komórce
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
pMemCell->UpdateValues( NULL, 0, int( pMemCell->Value2() ) | 1,
update_memval2); // zmieniamy ostatnią wartość na nieparzystą
#else
pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) | 1, update_memval2 ); // zmieniamy ostatnią wartość na nieparzystą pMemCell->UpdateValues( "", 0, int( pMemCell->Value2() ) | 1, update_memval2 ); // zmieniamy ostatnią wartość na nieparzystą
#endif
} }
} }
}; };
@@ -154,9 +144,6 @@ void TIsolated::Modify(int i, TDynamicObject *o)
TTrack::TTrack(TGroundNode *g) : TTrack::TTrack(TGroundNode *g) :
pMyNode( g ) // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode pMyNode( g ) // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
{ {
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
::SecureZeroMemory( Dynamics, sizeof( Dynamics ) );
#endif
fRadiusTable[ 0 ] = 0.0; fRadiusTable[ 0 ] = 0.0;
fRadiusTable[ 1 ] = 0.0; fRadiusTable[ 1 ] = 0.0;
nFouling[ 0 ] = nullptr; nFouling[ 0 ] = nullptr;
@@ -199,7 +186,7 @@ void TTrack::Init()
break; break;
case tt_Table: // oba potrzebne case tt_Table: // oba potrzebne
SwitchExtension = std::make_shared<TSwitchExtension>( this, 1 ); // kopia oryginalnego toru SwitchExtension = std::make_shared<TSwitchExtension>( this, 1 ); // kopia oryginalnego toru
Segment = make_shared<TSegment>(this); Segment = std::make_shared<TSegment>(this);
break; break;
} }
} }
@@ -413,7 +400,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
{ // pobranie obiektu trajektorii ruchu { // pobranie obiektu trajektorii ruchu
vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
double a1, a2, r1, r2, r3, r4; double a1, a2, r1, r2, r3, r4;
string str; std::string str;
size_t i; //,state; //Ra: teraz już nie ma początkowego stanu zwrotnicy we wpisie size_t i; //,state; //Ra: teraz już nie ma początkowego stanu zwrotnicy we wpisie
std::string token; std::string token;
@@ -554,8 +541,10 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
p2.y += 0.18; p2.y += 0.18;
// na przechyłce doliczyć jeszcze pół przechyłki // na przechyłce doliczyć jeszcze pół przechyłki
} }
if (fRadius != 0) // gdy podany promień if( fRadius != 0 ) // gdy podany promień
segsize = Min0R(5.0, 0.2 + fabs(fRadius) * 0.02); // do 250m - 5, potem 1 co 50m segsize = Min0R( 5.0, 0.2 + fabs( fRadius ) * 0.02 ); // do 250m - 5, potem 1 co 50m
else
segsize = 10.0; // for straights, 10m per segment works good enough
if ((((p1 + p1 + p2) / 3.0 - p1 - cp1).Length() < 0.02) || if ((((p1 + p1 + p2) / 3.0 - p1 - cp1).Length() < 0.02) ||
(((p1 + p2 + p2) / 3.0 - p2 + cp1).Length() < 0.02)) (((p1 + p2 + p2) / 3.0 - p2 + cp1).Length() < 0.02))
@@ -563,11 +552,9 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
if ((cp1 == vector3(0, 0, 0)) && if ((cp1 == vector3(0, 0, 0)) &&
(cp2 == vector3(0, 0, 0))) // Ra: hm, czasem dla prostego są podane... (cp2 == vector3(0, 0, 0))) // Ra: hm, czasem dla prostego są podane...
Segment->Init(p1, p2, segsize, r1, Segment->Init(p1, p2, segsize, r1, r2); // gdy prosty, kontrolne wyliczane przy zmiennej przechyłce
r2); // gdy prosty, kontrolne wyliczane przy zmiennej przechyłce
else else
Segment->Init(p1, cp1 + p1, cp2 + p2, p2, segsize, r1, Segment->Init(p1, cp1 + p1, cp2 + p2, p2, segsize, r1, r2); // gdy łuk (ustawia bCurve=true)
r2); // gdy łuk (ustawia bCurve=true)
if ((r1 != 0) || (r2 != 0)) if ((r1 != 0) || (r2 != 0))
iTrapezoid = 1; // są przechyłki do uwzględniania w rysowaniu iTrapezoid = 1; // są przechyłki do uwzględniania w rysowaniu
if (eType == tt_Table) // obrotnica ma doklejkę if (eType == tt_Table) // obrotnica ma doklejkę
@@ -808,7 +795,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
} }
// alternatywny zapis nazwy odcinka izolowanego - po znaku "@" w nazwie toru // alternatywny zapis nazwy odcinka izolowanego - po znaku "@" w nazwie toru
if (!pIsolated) if (!pIsolated)
if ((i = name.find("@")) != string::npos) if ((i = name.find("@")) != std::string::npos)
if (i < name.length()) // nie może być puste if (i < name.length()) // nie może być puste
{ {
pIsolated = TIsolated::Find(name.substr(i + 1, name.length())); pIsolated = TIsolated::Find(name.substr(i + 1, name.length()));
@@ -976,7 +963,7 @@ bool TTrack::AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus)
return false; return false;
}; };
string TTrack::IsolatedName() std::string TTrack::IsolatedName()
{ // podaje nazwę odcinka izolowanego, jesli nie ma on jeszcze przypisanych zdarzeń { // podaje nazwę odcinka izolowanego, jesli nie ma on jeszcze przypisanych zdarzeń
if (pIsolated) if (pIsolated)
if (!pIsolated->evBusy && !pIsolated->evFree) if (!pIsolated->evBusy && !pIsolated->evFree)
@@ -1007,27 +994,6 @@ bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
Dynamic->MyTrack = NULL; // trzeba by to uzależnić od kierunku ruchu... Dynamic->MyTrack = NULL; // trzeba by to uzależnić od kierunku ruchu...
return true; return true;
} }
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if (Global::iMultiplayer) // jeśli multiplayer
if (!iNumDynamics) // pierwszy zajmujący
if (pMyNode->asName != "none")
Global::pGround->WyslijString(pMyNode->asName,
8); // przekazanie informacji o zajętości toru
if (iNumDynamics < iMaxNumDynamics)
{ // jeśli jest miejsce, dajemy na koniec
Dynamics[iNumDynamics++] = Dynamic;
Dynamic->MyTrack = this; // ABu: na ktorym torze jesteśmy
if (Dynamic->iOverheadMask) // jeśli ma pantografy
Dynamic->OverheadTrack(
fOverhead); // przekazanie informacji o jeździe bezprądowej na tym odcinku toru
return true;
}
else
{
Error("Too many dynamics on track " + pMyNode->asName);
return false;
}
#else
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
// jeśli multiplayer // jeśli multiplayer
if( true == Dynamics.empty() ) { if( true == Dynamics.empty() ) {
@@ -1045,7 +1011,6 @@ bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
Dynamic->OverheadTrack( fOverhead ); // przekazanie informacji o jeździe bezprądowej na tym odcinku toru Dynamic->OverheadTrack( fOverhead ); // przekazanie informacji o jeździe bezprądowej na tym odcinku toru
} }
return true; return true;
#endif
}; };
void TTrack::MoveMe(vector3 pPosition) void TTrack::MoveMe(vector3 pPosition)
@@ -1863,42 +1828,16 @@ void TTrack::Render()
bool TTrack::CheckDynamicObject(TDynamicObject *Dynamic) bool TTrack::CheckDynamicObject(TDynamicObject *Dynamic)
{ // sprawdzenie, czy pojazd jest przypisany do toru { // sprawdzenie, czy pojazd jest przypisany do toru
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for (int i = 0; i < iNumDynamics; i++)
if (Dynamic == Dynamics[i])
return true;
return false;
#else
for( auto dynamic : Dynamics ) { for( auto dynamic : Dynamics ) {
if( dynamic == Dynamic ) { if( dynamic == Dynamic ) {
return true; return true;
} }
} }
return false; return false;
#endif
}; };
bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic) bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic)
{ // usunięcie pojazdu z listy przypisanych do toru { // usunięcie pojazdu z listy przypisanych do toru
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for (int i = 0; i < iNumDynamics; i++)
{ // sprawdzanie wszystkich po kolei
if (Dynamic == Dynamics[i])
{ // znaleziony, przepisanie następnych, żeby dziur nie było
--iNumDynamics;
for (i; i < iNumDynamics; i++)
Dynamics[i] = Dynamics[i + 1];
if (Global::iMultiplayer) // jeśli multiplayer
if (!iNumDynamics) // jeśli już nie ma żadnego
if (pMyNode->asName != "none")
Global::pGround->WyslijString(
pMyNode->asName, 9); // przekazanie informacji o zwolnieniu toru
return true;
}
}
Error("Cannot remove dynamic from track");
return false;
#else
bool result = false; bool result = false;
if( *Dynamics.begin() == Dynamic ) { if( *Dynamics.begin() == Dynamic ) {
// most likely the object getting removed is at the front... // most likely the object getting removed is at the front...
@@ -1935,7 +1874,6 @@ bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic)
} }
return result; return result;
#endif
} }
bool TTrack::InMovement() bool TTrack::InMovement()
@@ -2457,8 +2395,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start)
} }
}; };
void TTrack::RaRenderVBO(int iPtr) void TTrack::RaRenderVBO( int iPtr ) { // renderowanie z użyciem VBO
{ // renderowanie z użyciem VBO
// Ra 2014-07: trzeba wymienić GL_TRIANGLE_STRIP na GL_TRIANGLES i renderować trójkąty sektora // Ra 2014-07: trzeba wymienić GL_TRIANGLE_STRIP na GL_TRIANGLES i renderować trójkąty sektora
// dla kolejnych tekstur! // dla kolejnych tekstur!
EnvironmentSet(); EnvironmentSet();
@@ -2598,7 +2535,7 @@ void TTrack::EnvironmentSet()
#else #else
switch( eEnvironment ) { switch( eEnvironment ) {
case e_canyon: { case e_canyon: {
Global::daylight.intensity = 0.5f; Global::daylight.intensity = 0.4f;
break; break;
} }
case e_tunnel: { case e_tunnel: {
@@ -2640,14 +2577,6 @@ void TTrack::EnvironmentReset()
void TTrack::RenderDyn() void TTrack::RenderDyn()
{ // renderowanie nieprzezroczystych fragmentów pojazdów { // renderowanie nieprzezroczystych fragmentów pojazdów
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if (!iNumDynamics)
return; // po co kombinować, jeśli nie ma pojazdów?
// EnvironmentSet(); //Ra: pojazdy sobie same teraz liczą cienie
for (int i = 0; i < iNumDynamics; i++)
Dynamics[i]->Render(); // sam sprawdza, czy VBO; zmienia kontekst VBO!
// EnvironmentReset();
#else
for( auto dynamic : Dynamics ) { for( auto dynamic : Dynamics ) {
// sam sprawdza, czy VBO; zmienia kontekst VBO! // sam sprawdza, czy VBO; zmienia kontekst VBO!
#ifdef EU07_USE_OLD_RENDERCODE #ifdef EU07_USE_OLD_RENDERCODE
@@ -2656,19 +2585,10 @@ void TTrack::RenderDyn()
GfxRenderer.Render( dynamic ); GfxRenderer.Render( dynamic );
#endif #endif
} }
#endif
}; };
void TTrack::RenderDynAlpha() void TTrack::RenderDynAlpha()
{ // renderowanie przezroczystych fragmentów pojazdów { // renderowanie przezroczystych fragmentów pojazdów
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
if (!iNumDynamics)
return; // po co kombinować, jeśli nie ma pojazdów?
// EnvironmentSet(); //Ra: pojazdy sobie same teraz liczą cienie
for (int i = 0; i < iNumDynamics; i++)
Dynamics[i]->RenderAlpha(); // sam sprawdza, czy VBO; zmienia kontekst VBO!
// EnvironmentReset();
#else
for( auto dynamic : Dynamics ) { for( auto dynamic : Dynamics ) {
// sam sprawdza, czy VBO; zmienia kontekst VBO! // sam sprawdza, czy VBO; zmienia kontekst VBO!
#ifdef EU07_USE_OLD_RENDERCODE #ifdef EU07_USE_OLD_RENDERCODE
@@ -2677,19 +2597,13 @@ void TTrack::RenderDynAlpha()
GfxRenderer.Render_Alpha( dynamic ); GfxRenderer.Render_Alpha( dynamic );
#endif #endif
} }
#endif
}; };
void TTrack::RenderDynSounds() void TTrack::RenderDynSounds()
{ // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania { // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for( int i = 0; i < iNumDynamics; i++ )
Dynamics[i]->RenderSounds();
#else
for( auto dynamic : Dynamics ) { for( auto dynamic : Dynamics ) {
dynamic->RenderSounds(); dynamic->RenderSounds();
} }
#endif
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool TTrack::SetConnections(int i) bool TTrack::SetConnections(int i)
@@ -2923,8 +2837,7 @@ TTrack * TTrack::RaAnimate()
m = false; // koniec animacji m = false; // koniec animacji
} }
} }
if (Global::bUseVBO)
{ // dla OpenGL 1.4 odświeży się cały sektor, w późniejszych poprawiamy fragment
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
if (TextureID1) // Ra: !!!! tu jest do poprawienia if (TextureID1) // Ra: !!!! tu jest do poprawienia
{ // iglice liczone tylko dla zwrotnic { // iglice liczone tylko dla zwrotnic
@@ -2992,9 +2905,6 @@ TTrack * TTrack::RaAnimate()
2 * 2 * 12 * sizeof(CVertNormTex), &Vert); // wysłanie fragmentu bufora VBO 2 * 2 * 12 * sizeof(CVertNormTex), &Vert); // wysłanie fragmentu bufora VBO
} }
} }
else // gdy Display List
Release(); // niszczenie skompilowanej listy, aby się wygenerowała nowa
}
else if (eType == tt_Table) // dla obrotnicy - szyny i podsypka else if (eType == tt_Table) // dla obrotnicy - szyny i podsypka
{ {
if (SwitchExtension->pModel && if (SwitchExtension->pModel &&
@@ -3023,18 +2933,12 @@ TTrack * TTrack::RaAnimate()
SwitchExtension->vTrans; // SwitchExtension->Segments[0]->FastGetPoint(0.5); SwitchExtension->vTrans; // SwitchExtension->Segments[0]->FastGetPoint(0.5);
Segment->Init(middle + vector3(sina, 0.0, cosa), Segment->Init(middle + vector3(sina, 0.0, cosa),
middle - vector3(sina, 0.0, cosa), 5.0); // nowy odcinek middle - vector3(sina, 0.0, cosa), 5.0); // nowy odcinek
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for( int i = 0; i < iNumDynamics; i++ )
Dynamics[i]->Move(0.000001); // minimalny ruch, aby przeliczyć pozycję i
#else
for( auto dynamic : Dynamics ) { for( auto dynamic : Dynamics ) {
// minimalny ruch, aby przeliczyć pozycję // minimalny ruch, aby przeliczyć pozycję
dynamic->Move( 0.000001 ); dynamic->Move( 0.000001 );
} }
#endif
// kąty // kąty
if (Global::bUseVBO)
{ // dla OpenGL 1.4 odświeży się cały sektor, w późniejszych poprawiamy fragment
// aktualizacja pojazdów na torze // aktualizacja pojazdów na torze
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
{ {
@@ -3050,9 +2954,6 @@ TTrack * TTrack::RaAnimate()
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex), GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
size * sizeof(CVertNormTex), Vert); // wysłanie fragmentu bufora VBO size * sizeof(CVertNormTex), Vert); // wysłanie fragmentu bufora VBO
} }
}
else // gdy Display List
Release(); // niszczenie skompilowanej listy, aby się wygenerowała nowa
} // animacja trwa nadal } // animacja trwa nadal
} }
else else
@@ -3063,15 +2964,9 @@ TTrack * TTrack::RaAnimate()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TTrack::RadioStop() void TTrack::RadioStop()
{ // przekazanie pojazdom rozkazu zatrzymania { // przekazanie pojazdom rozkazu zatrzymania
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
for (int i = 0; i < iNumDynamics; i++)
Dynamics[i]->RadioStop();
#else
for( auto dynamic : Dynamics ) { for( auto dynamic : Dynamics ) {
dynamic->RadioStop(); dynamic->RadioStop();
} }
#endif
}; };
double TTrack::WidthTotal() double TTrack::WidthTotal()
@@ -3180,7 +3075,7 @@ void TTrack::MovedUp1(double dh)
fTexHeight1 += dh; fTexHeight1 += dh;
}; };
string TTrack::NameGet() std::string TTrack::NameGet()
{ // ustalenie nazwy toru { // ustalenie nazwy toru
if (this) if (this)
if (pMyNode) if (pMyNode)

13
Track.h
View File

@@ -95,10 +95,6 @@ class TSwitchExtension
private: private:
}; };
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
const int iMaxNumDynamics = 40; // McZapkie-100303
#endif
class TIsolated class TIsolated
{ // obiekt zbierający zajętości z kilku odcinków { // obiekt zbierający zajętości z kilku odcinków
int iAxles = 0; // ilość osi na odcinkach obsługiwanych przez obiekt int iAxles = 0; // ilość osi na odcinkach obsługiwanych przez obiekt
@@ -152,13 +148,8 @@ class TTrack : public Resource
TGroundNode * TGroundNode *
pMyNode = nullptr; // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode pMyNode = nullptr; // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
public: public:
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
int iNumDynamics = 0;
TDynamicObject *Dynamics[iMaxNumDynamics];
#else
typedef std::deque<TDynamicObject *> dynamics_sequence; typedef std::deque<TDynamicObject *> dynamics_sequence;
dynamics_sequence Dynamics; dynamics_sequence Dynamics;
#endif
int iEvents = 0; // Ra: flaga informująca o obecności eventów int iEvents = 0; // Ra: flaga informująca o obecności eventów
TEvent *evEventall0 = nullptr; // McZapkie-140302: wyzwalany gdy pojazd stoi TEvent *evEventall0 = nullptr; // McZapkie-140302: wyzwalany gdy pojazd stoi
TEvent *evEventall1 = nullptr; TEvent *evEventall1 = nullptr;
@@ -204,11 +195,7 @@ class TTrack : public Resource
TTrack * NullCreate(int dir); TTrack * NullCreate(int dir);
inline bool IsEmpty() inline bool IsEmpty()
{ {
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
return (iNumDynamics <= 0);
#else
return Dynamics.empty(); return Dynamics.empty();
#endif
}; };
void ConnectPrevPrev(TTrack *pNewPrev, int typ); void ConnectPrevPrev(TTrack *pNewPrev, int typ);
void ConnectPrevNext(TTrack *pNewPrev, int typ); void ConnectPrevNext(TTrack *pNewPrev, int typ);

View File

@@ -105,139 +105,12 @@ TTraction::TTraction()
TTraction::~TTraction() TTraction::~TTraction()
{ {
if (!Global::bUseVBO)
glDeleteLists(uiDisplayList, 1);
} }
void TTraction::Optimize() void TTraction::Optimize()
{ {
if (Global::bUseVBO)
return;
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
GfxRenderer.Bind(0);
// glColor3ub(0,0,0); McZapkie: to do render
// glPushMatrix();
// glTranslatef(pPosition.x,pPosition.y,pPosition.z);
if (Wires != 0)
{
// Dlugosc odcinka trakcji 'Winger
double ddp = hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z);
if (Wires == 2)
WireOffset = 0;
// Przewoz jezdny 1 'Marcin
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint1.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pPoint1.y,
pPoint1.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
glVertex3f(pPoint2.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pPoint2.y,
pPoint2.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
glEnd();
// Nie wiem co 'Marcin
Math3D::vector3 pt1, pt2, pt3, pt4, v1, v2;
v1 = pPoint4 - pPoint3;
v2 = pPoint2 - pPoint1;
float step = 0;
if (iNumSections > 0)
step = 1.0f / (float)iNumSections;
float f = step;
float mid = 0.5;
float t;
// Przewod nosny 'Marcin
if (Wires != 1)
{
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint3.x, pPoint3.y, pPoint3.z);
for (int i = 0; i < iNumSections - 1; i++)
{
pt3 = pPoint3 + v1 * f;
t = (1 - fabs(f - mid) * 2);
if ((Wires < 4) || ((i != 0) && (i != iNumSections - 2)))
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference, pt3.z);
f += step;
}
glVertex3f(pPoint4.x, pPoint4.y, pPoint4.z);
glEnd();
}
// Drugi przewod jezdny 'Winger
if (Wires > 2)
{
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pPoint1.y,
pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
glVertex3f(pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pPoint2.y,
pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
glEnd();
}
f = step;
if (Wires == 4)
{
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint3.x, pPoint3.y - 0.65f * fHeightDifference, pPoint3.z);
for (int i = 0; i < iNumSections - 1; i++)
{
pt3 = pPoint3 + v1 * f;
t = (1 - fabs(f - mid) * 2);
glVertex3f(
pt3.x,
pt3.y - sqrt(t) * fHeightDifference -
((i == 0) || (i == iNumSections - 2) ? 0.25f * fHeightDifference : +0.05),
pt3.z);
f += step;
}
glVertex3f(pPoint4.x, pPoint4.y - 0.65f * fHeightDifference, pPoint4.z);
glEnd();
}
f = step;
// Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
if (Wires != 1)
{
glBegin(GL_LINES);
for (int i = 0; i < iNumSections - 1; i++)
{
float flo, flo1;
flo = (Wires == 4 ? 0.25f * fHeightDifference : 0);
flo1 = (Wires == 4 ? +0.05 : 0);
pt3 = pPoint3 + v1 * f;
pt4 = pPoint1 + v2 * f;
t = (1 - fabs(f - mid) * 2);
if ((i % 2) == 0)
{
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference -
((i == 0) || (i == iNumSections - 2) ? flo : flo1),
pt3.z);
glVertex3f(pt4.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pt4.y,
pt4.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
}
else
{
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference -
((i == 0) || (i == iNumSections - 2) ? flo : flo1),
pt3.z);
glVertex3f(pt4.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pt4.y,
pt4.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
}
if ((Wires == 4) && ((i == 1) || (i == iNumSections - 3)))
{
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference - 0.05, pt3.z);
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference, pt3.z);
}
// endif;
f += step;
}
glEnd();
}
glEndList();
}
} }
/* /*
void TTraction::InitCenter(vector3 Angles, vector3 pOrigin) void TTraction::InitCenter(vector3 Angles, vector3 pOrigin)

View File

@@ -391,9 +391,9 @@ PyObject *TTrain::GetTrainState() {
PyDict_SetItemString( dict, "actualproximitydist", PyGetFloat( driver->ActualProximityDist ) ); PyDict_SetItemString( dict, "actualproximitydist", PyGetFloat( driver->ActualProximityDist ) );
PyDict_SetItemString( dict, "trainnumber", PyGetString( driver->TrainName().c_str() ) ); PyDict_SetItemString( dict, "trainnumber", PyGetString( driver->TrainName().c_str() ) );
// world state data // world state data
PyDict_SetItemString( dict, "hours", PyGetInt( GlobalTime->hh ) ); PyDict_SetItemString( dict, "hours", PyGetInt( Simulation::Time.data().wHour ) );
PyDict_SetItemString( dict, "minutes", PyGetInt( GlobalTime->mm ) ); PyDict_SetItemString( dict, "minutes", PyGetInt( Simulation::Time.data().wMinute ) );
PyDict_SetItemString( dict, "seconds", PyGetInt( GlobalTime->mr ) ); PyDict_SetItemString( dict, "seconds", PyGetInt( Simulation::Time.second() ) );
return dict; return dict;
} }
@@ -2659,7 +2659,7 @@ bool TTrain::Update( double const Deltatime )
fTachoVelocity = Min0R(fabs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot), fTachoVelocity = Min0R(fabs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot),
mvControlled->Vmax * 1.05); mvControlled->Vmax * 1.05);
{ // skacze osobna zmienna { // skacze osobna zmienna
float ff = floor(GlobalTime->mr); // skacze co sekunde - pol sekundy float ff = Simulation::Time.data().wSecond; // skacze co sekunde - pol sekundy
// pomiar, pol sekundy ustawienie // pomiar, pol sekundy ustawienie
if (ff != fTachoTimer) // jesli w tej sekundzie nie zmienial if (ff != fTachoTimer) // jesli w tej sekundzie nie zmienial
{ {
@@ -3337,11 +3337,11 @@ bool TTrain::Update( double const Deltatime )
// McZapkie-300302: zegarek // McZapkie-300302: zegarek
if (ggClockMInd.SubModel) if (ggClockMInd.SubModel)
{ {
ggClockSInd.UpdateValue(int(GlobalTime->mr)); ggClockSInd.UpdateValue(Simulation::Time.data().wSecond);
ggClockSInd.Update(); ggClockSInd.Update();
ggClockMInd.UpdateValue(GlobalTime->mm); ggClockMInd.UpdateValue(Simulation::Time.data().wMinute);
ggClockMInd.Update(); ggClockMInd.Update();
ggClockHInd.UpdateValue(GlobalTime->hh + GlobalTime->mm / 60.0); ggClockHInd.UpdateValue(Simulation::Time.data().wHour + Simulation::Time.data().wMinute / 60.0);
ggClockHInd.Update(); ggClockHInd.Update();
} }

557
World.cpp
View File

@@ -43,11 +43,148 @@ std::shared_ptr<ui_panel> UIHeader = std::make_shared<ui_panel>( 20, 20 ); // he
std::shared_ptr<ui_panel> UITable = std::make_shared<ui_panel>( 20, 100 ); // schedule or scan table std::shared_ptr<ui_panel> UITable = std::make_shared<ui_panel>( 20, 100 ); // schedule or scan table
std::shared_ptr<ui_panel> UITranscripts = std::make_shared<ui_panel>( 85, 600 ); // voice transcripts std::shared_ptr<ui_panel> UITranscripts = std::make_shared<ui_panel>( 85, 600 ); // voice transcripts
namespace Simulation {
simulation_time Time;
}
extern "C" extern "C"
{ {
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); //m7todo: potrzebne do directsound GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); //m7todo: potrzebne do directsound
} }
void
simulation_time::init() {
char monthdaycounts[ 2 ][ 13 ] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) );
// cache requested elements, if any
WORD const requestedhour = m_time.wHour;
WORD const requestedminute = m_time.wMinute;
::GetLocalTime( &m_time );
if( Global::fMoveLight > 0.0 ) {
// day and month of the year can be overriden by scenario setup
daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast<WORD>( Global::fMoveLight ) );
}
if( requestedhour != (WORD)-1 ) { m_time.wHour = clamp( requestedhour, static_cast<WORD>( 0 ), static_cast<WORD>( 23 ) ); }
if( requestedminute != (WORD)-1 ) { m_time.wMinute = clamp( requestedminute, static_cast<WORD>( 0 ), static_cast<WORD>( 59 ) ); }
// if the time is taken from the local clock leave the seconds intact, otherwise set them to zero
if( ( requestedhour != (WORD)-1 ) || ( requestedminute != (WORD)-1 ) ) {
m_time.wSecond = 0;
}
m_yearday = yearday( m_time.wDay, m_time.wMonth, m_time.wYear );
}
void
simulation_time::update( double const Deltatime ) {
// use large enough buffer to hold long time skips
auto milliseconds = m_time.wMilliseconds + static_cast<size_t>(std::floor( 1000.0 * Deltatime ));
while( milliseconds >= 1000.0 ) {
++m_time.wSecond;
milliseconds -= 1000;
}
m_time.wMilliseconds = (WORD)milliseconds;
while( m_time.wSecond >= 60 ) {
++m_time.wMinute;
m_time.wSecond -= 60;
}
while( m_time.wMinute >= 60 ) {
++m_time.wHour;
m_time.wMinute -= 60;
}
while( m_time.wHour >= 24 ) {
++m_time.wDay;
++m_time.wDayOfWeek;
if( m_time.wDayOfWeek >= 7 ) {
m_time.wDayOfWeek -= 7;
}
m_time.wHour -= 24;
}
int leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 );
while( m_time.wDay > m_monthdaycounts[ leap ][ m_time.wMonth ] ) {
m_time.wDay -= m_monthdaycounts[ leap ][ m_time.wMonth ];
++m_time.wMonth;
// unlikely but we might've entered a new year
if( m_time.wMonth > 12 ) {
++m_time.wYear;
leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 );
m_time.wMonth -= 12;
}
}
}
int
simulation_time::yearday( int Day, const int Month, const int Year ) {
char daytab[ 2 ][ 13 ] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
int i, leap;
leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
for( i = 1; i < Month; ++i )
Day += daytab[ leap ][ i ];
return Day;
}
void
simulation_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) {
WORD daytab[ 2 ][ 13 ] = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
WORD idx = 1;
while( ( idx < 13 ) && ( Yearday >= daytab[ leap ][ idx ] ) ) {
++idx;
}
Month = idx;
Day = Yearday - daytab[ leap ][ idx - 1 ];
}
int
simulation_time::julian_day() const {
int yy = ( m_time.wYear < 0 ? m_time.wYear + 1 : m_time.wYear ) - std::floor( ( 12 - m_time.wMonth ) / 10.f );
int mm = m_time.wMonth + 9;
if( mm >= 12 ) { mm -= 12; }
int K1 = std::floor( 365.25 * ( yy + 4712 ) );
int K2 = std::floor( 30.6 * mm + 0.5 );
// for dates in Julian calendar
int JD = K1 + K2 + m_time.wDay + 59;
// for dates in Gregorian calendar; 2299160 is October 15th, 1582
const int gregorianswitchday = 2299160;
if( JD > gregorianswitchday ) {
int K3 = std::floor( std::floor( ( yy * 0.01 ) + 49 ) * 0.75 ) - 38;
JD -= K3;
}
return JD;
}
TWorld::TWorld() TWorld::TWorld()
{ {
// randomize(); // randomize();
@@ -58,9 +195,6 @@ TWorld::TWorld()
KeyEvents[i] = NULL; // eventy wyzwalane klawiszami cyfrowymi KeyEvents[i] = NULL; // eventy wyzwalane klawiszami cyfrowymi
Global::iSlowMotion = 0; Global::iSlowMotion = 0;
// Global::changeDynObj=NULL; // Global::changeDynObj=NULL;
OutText1 = ""; // teksty wyświetlane na ekranie
OutText2 = "";
OutText3 = "";
pDynamicNearest = NULL; pDynamicNearest = NULL;
fTimeBuffer = 0.0; // bufor czasu aktualizacji dla stałego kroku fizyki fTimeBuffer = 0.0; // bufor czasu aktualizacji dla stałego kroku fizyki
fMaxDt = 0.01; //[s] początkowy krok czasowy fizyki fMaxDt = 0.01; //[s] początkowy krok czasowy fizyki
@@ -153,7 +287,6 @@ bool TWorld::Init( GLFWwindow *Window ) {
Global::pCamera = &Camera; // Ra: wskaźnik potrzebny do likwidacji drgań Global::pCamera = &Camera; // Ra: wskaźnik potrzebny do likwidacji drgań
WriteLog("\nStarting MaSzyna rail vehicle simulator."); WriteLog("\nStarting MaSzyna rail vehicle simulator.");
WriteLog(Global::asVersion);
WriteLog("Online documentation and additional files on http://eu07.pl"); WriteLog("Online documentation and additional files on http://eu07.pl");
WriteLog("Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, " WriteLog("Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, "
"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");
@@ -180,6 +313,8 @@ bool TWorld::Init( GLFWwindow *Window ) {
glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii
Simulation::Time.init();
Environment.init(); Environment.init();
Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]); Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]);
@@ -270,14 +405,55 @@ bool TWorld::Init( GLFWwindow *Window ) {
}; };
void TWorld::OnKeyDown(int cKey) void TWorld::OnKeyDown(int cKey)
{ //(cKey) to kod klawisza, cyfrowe i literowe się zgadzają {
// Ra 2014-09: tu by można dodać tabelę konwersji: 256 wirtualnych kodów w kontekście dwóch // dump keypress info in the log
// przełączników [Shift] i [Ctrl] if( !Global::iPause ) {
// na każdy kod wirtualny niech przypadają 4 bajty: 2 dla naciśnięcia i 2 dla zwolnienia // podczas pauzy klawisze nie działają
// powtórzone 256 razy da 1kB na każdy stan przełączników, łącznie będzie 4kB pierwszej tabeli std::string keyinfo;
// przekodowania auto keyname = glfwGetKeyName( cKey, 0 );
//m7todo: printowanie klawiszy? if( keyname != nullptr ) {
if (cKey >= '0' && cKey <= '9') keyinfo += std::string( keyname );
}
else {
switch( cKey ) {
case GLFW_KEY_SPACE: { keyinfo += "Space"; break; }
case GLFW_KEY_ENTER: { keyinfo += "Enter"; break; }
case GLFW_KEY_ESCAPE: { keyinfo += "Esc"; break; }
case GLFW_KEY_TAB: { keyinfo += "Tab"; break; }
case GLFW_KEY_INSERT: { keyinfo += "Insert"; break; }
case GLFW_KEY_DELETE: { keyinfo += "Delete"; break; }
case GLFW_KEY_HOME: { keyinfo += "Home"; break; }
case GLFW_KEY_END: { keyinfo += "End"; break; }
case GLFW_KEY_F1: { keyinfo += "F1"; break; }
case GLFW_KEY_F2: { keyinfo += "F2"; break; }
case GLFW_KEY_F3: { keyinfo += "F3"; break; }
case GLFW_KEY_F4: { keyinfo += "F4"; break; }
case GLFW_KEY_F5: { keyinfo += "F5"; break; }
case GLFW_KEY_F6: { keyinfo += "F6"; break; }
case GLFW_KEY_F7: { keyinfo += "F7"; break; }
case GLFW_KEY_F8: { keyinfo += "F8"; break; }
case GLFW_KEY_F9: { keyinfo += "F9"; break; }
case GLFW_KEY_F10: { keyinfo += "F10"; break; }
case GLFW_KEY_F11: { keyinfo += "F11"; break; }
case GLFW_KEY_F12: { keyinfo += "F12"; break; }
}
}
if( keyinfo.empty() == false ) {
std::string keymodifiers;
if( Global::shiftState )
keymodifiers += "[Shift]+";
if( Global::ctrlState )
keymodifiers += "[Ctrl]+";
WriteLog( "Key pressed: " + keymodifiers + "[" + keyinfo + "]" );
}
}
// actual key processing
// TODO: redo the input system
if( ( cKey >= GLFW_KEY_0 ) && ( cKey <= GLFW_KEY_9 ) ) // klawisze cyfrowe
{ {
int i = cKey - '0'; // numer klawisza int i = cKey - '0'; // numer klawisza
if (Global::shiftState) if (Global::shiftState)
@@ -330,11 +506,11 @@ void TWorld::OnKeyDown(int cKey)
// additional time speedup keys in debug mode // additional time speedup keys in debug mode
if (Global::ctrlState) { if (Global::ctrlState) {
// ctrl-f3 // ctrl-f3
GlobalTime->UpdateMTableTime( 20.0 * 60.0 ); Simulation::Time.update( 20.0 * 60.0 );
} }
else if (Global::shiftState) { else if (Global::shiftState) {
// shift-f3 // shift-f3
GlobalTime->UpdateMTableTime( 5.0 * 60.0 ); Simulation::Time.update( 5.0 * 60.0 );
} }
} }
if( (!Global::ctrlState) if( (!Global::ctrlState)
@@ -774,20 +950,19 @@ bool TWorld::Update()
if( (Global::iPause == false) if( (Global::iPause == false)
|| (m_init == false) ) || (m_init == false) )
{ // jak pauza, to nie ma po co tego przeliczać { // jak pauza, to nie ma po co tego przeliczać
GlobalTime->UpdateMTableTime(Timer::GetDeltaTime()); // McZapkie-300302: czas rozkladowy
// Ra 2014-07: przeliczenie kąta czasu (do animacji zależnych od czasu) // Ra 2014-07: przeliczenie kąta czasu (do animacji zależnych od czasu)
Global::fTimeAngleDeg = Simulation::Time.update( Timer::GetDeltaTime() );
GlobalTime->hh * 15.0 + GlobalTime->mm * 0.25 + GlobalTime->mr / 240.0; auto const &time = Simulation::Time.data();
Global::fClockAngleDeg[0] = 36.0 * (int(GlobalTime->mr) % 10); // jednostki sekund Global::fTimeAngleDeg = time.wHour * 15.0 + time.wMinute * 0.25 + ( ( time.wSecond + 0.001 * time.wMilliseconds ) / 240.0 );
Global::fClockAngleDeg[1] = 36.0 * (int(GlobalTime->mr) / 10); // dziesiątki sekund Global::fClockAngleDeg[ 0 ] = 36.0 * ( time.wSecond % 10 ); // jednostki sekund
Global::fClockAngleDeg[2] = 36.0 * (GlobalTime->mm % 10); // jednostki minut Global::fClockAngleDeg[ 1 ] = 36.0 * ( time.wSecond / 10 ); // dziesiątki sekund
Global::fClockAngleDeg[3] = 36.0 * (GlobalTime->mm / 10); // dziesiątki minut Global::fClockAngleDeg[ 2 ] = 36.0 * ( time.wMinute % 10 ); // jednostki minut
Global::fClockAngleDeg[4] = 36.0 * (GlobalTime->hh % 10); // jednostki godzin Global::fClockAngleDeg[ 3 ] = 36.0 * ( time.wMinute / 10 ); // dziesiątki minut
Global::fClockAngleDeg[5] = 36.0 * (GlobalTime->hh / 10); // dziesiątki godzin Global::fClockAngleDeg[ 4 ] = 36.0 * ( time.wHour % 10 ); // jednostki godzin
Global::fClockAngleDeg[ 5 ] = 36.0 * ( time.wHour / 10 ); // dziesiątki godzin
Update_Environment(); Update_Environment();
} // koniec działań niewykonywanych podczas pauzy } // koniec działań niewykonywanych podczas pauzy
// poprzednie jakoś tam działało
// fixed step, simulation time based updates // fixed step, simulation time based updates
@@ -1173,7 +1348,6 @@ TWorld::Render_Cab() {
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka // ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
return; return;
} }
/* /*
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka // ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) && if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) &&
@@ -1407,6 +1581,7 @@ TWorld::Render_Cab() {
} }
#endif #endif
#ifdef EU07_USE_OLD_RENDERCODE
if( Global::bUseVBO ) { if( Global::bUseVBO ) {
// renderowanie z użyciem VBO. NOTE: needs update, and eventual merge into single render path down the road // renderowanie z użyciem VBO. NOTE: needs update, and eventual merge into single render path down the road
dynamic->mdKabina->RaRender( 0.0, dynamic->Material()->replacable_skins, dynamic->Material()->textures_alpha ); dynamic->mdKabina->RaRender( 0.0, dynamic->Material()->replacable_skins, dynamic->Material()->textures_alpha );
@@ -1414,14 +1589,13 @@ TWorld::Render_Cab() {
} }
else { else {
// renderowanie z Display List // renderowanie z Display List
#ifdef EU07_USE_OLD_RENDERCODE
dynamic->mdKabina->Render( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha ); dynamic->mdKabina->Render( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
dynamic->mdKabina->RenderAlpha( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha ); dynamic->mdKabina->RenderAlpha( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
}
#else #else
GfxRenderer.Render( dynamic->mdKabina, dynamic->Material(), 0.0 ); GfxRenderer.Render( dynamic->mdKabina, dynamic->Material(), 0.0 );
GfxRenderer.Render_Alpha( dynamic->mdKabina, dynamic->Material(), 0.0 ); GfxRenderer.Render_Alpha( dynamic->mdKabina, dynamic->Material(), 0.0 );
#endif #endif
}
#ifdef EU07_USE_OLD_LIGHTING_MODEL #ifdef EU07_USE_OLD_LIGHTING_MODEL
// przywrócenie standardowych, bo zawsze są zmieniane // przywrócenie standardowych, bo zawsze są zmieniane
glLightfv( GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight ); glLightfv( GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight );
@@ -1445,20 +1619,21 @@ TWorld::Render_Cab() {
void void
TWorld::Update_UI() { TWorld::Update_UI() {
OutText1 = OutText2 = OutText3 = OutText4 = "";
UITable->text_lines.clear(); UITable->text_lines.clear();
std::string uitextline1, uitextline2, uitextline3, uitextline4;
switch( Global::iTextMode ) { switch( Global::iTextMode ) {
case( GLFW_KEY_F1 ) : { case( GLFW_KEY_F1 ) : {
// f1, default mode: current time and timetable excerpt // f1, default mode: current time and timetable excerpt
OutText1 = auto const &time = Simulation::Time.data();
uitextline1 =
"Time: " "Time: "
+ to_string( (int)GlobalTime->hh ) + ":" + to_string( time.wHour ) + ":"
+ ( GlobalTime->mm < 10 ? "0" : "" ) + to_string( GlobalTime->mm ) + ":" + ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
+ ( GlobalTime->mr < 10 ? "0" : "" ) + to_string( std::floor( GlobalTime->mr ) ); + ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
if( Global::iPause ) { if( Global::iPause ) {
OutText1 += " (paused)"; uitextline1 += " (paused)";
} }
if( Controlled && ( Controlled->Mechanik != nullptr ) ) { if( Controlled && ( Controlled->Mechanik != nullptr ) ) {
@@ -1466,21 +1641,21 @@ TWorld::Update_UI() {
auto const &mover = Controlled->MoverParameters; auto const &mover = Controlled->MoverParameters;
auto const &driver = Controlled->Mechanik; auto const &driver = Controlled->Mechanik;
OutText2 = "Throttle: " + to_string( driver->Controlling()->MainCtrlPos, 0, 2 ) + "+" + std::to_string( driver->Controlling()->ScndCtrlPos ); uitextline2 = "Throttle: " + to_string( driver->Controlling()->MainCtrlPos, 0, 2 ) + "+" + std::to_string( driver->Controlling()->ScndCtrlPos );
if( mover->ActiveDir > 0 ) { OutText2 += " D"; } if( mover->ActiveDir > 0 ) { uitextline2 += " D"; }
else if( mover->ActiveDir < 0 ) { OutText2 += " R"; } else if( mover->ActiveDir < 0 ) { uitextline2 += " R"; }
else { OutText2 += " N"; } else { uitextline2 += " N"; }
OutText3 = "Brakes:" + to_string( mover->fBrakeCtrlPos, 1, 5 ) + "+" + std::to_string( mover->LocalBrakePos ); uitextline3 = "Brakes:" + to_string( mover->fBrakeCtrlPos, 1, 5 ) + "+" + std::to_string( mover->LocalBrakePos );
if( Global::iScreenMode[ Global::iTextMode - GLFW_KEY_F1 ] == 1 ) { if( Global::iScreenMode[ Global::iTextMode - GLFW_KEY_F1 ] == 1 ) {
// detail mode on second key press // detail mode on second key press
OutText2 += uitextline2 +=
" Speed: " + std::to_string( static_cast<int>( std::floor( mover->Vel ) ) ) + " km/h" " Speed: " + std::to_string( static_cast<int>( std::floor( mover->Vel ) ) ) + " km/h"
+ " (limit: " + std::to_string( static_cast<int>( std::floor( driver->VelDesired ) ) ) + " km/h" + " (limit: " + std::to_string( static_cast<int>( std::floor( driver->VelDesired ) ) ) + " km/h"
+ ", next limit: " + std::to_string( static_cast<int>( std::floor( Controlled->Mechanik->VelNext ) ) ) + " km/h" + ", next limit: " + std::to_string( static_cast<int>( std::floor( Controlled->Mechanik->VelNext ) ) ) + " km/h"
+ " in " + to_string( Controlled->Mechanik->ActualProximityDist * 0.001, 1 ) + " km)"; + " in " + to_string( Controlled->Mechanik->ActualProximityDist * 0.001, 1 ) + " km)";
OutText3 += uitextline3 +=
" Pressure: " + to_string( mover->BrakePress * 100.0, 2 ) + " kPa" " Pressure: " + to_string( mover->BrakePress * 100.0, 2 ) + " kPa"
+ " (train pipe: " + to_string( mover->PipePress * 100.0, 2 ) + " kPa)"; + " (train pipe: " + to_string( mover->PipePress * 100.0, 2 ) + " kPa)";
} }
@@ -1502,21 +1677,22 @@ TWorld::Update_UI() {
auto const table = tmp->Mechanik->Timetable(); auto const table = tmp->Mechanik->Timetable();
if( table == nullptr ) { break; } if( table == nullptr ) { break; }
OutText1 = auto const &time = Simulation::Time.data();
uitextline1 =
"Time: " "Time: "
+ to_string( (int)GlobalTime->hh ) + ":" + to_string( time.wHour ) + ":"
+ ( GlobalTime->mm < 10 ? "0" : "" ) + to_string( GlobalTime->mm ) + ":" + ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
+ ( GlobalTime->mr < 10 ? "0" : "" ) + to_string( std::floor( GlobalTime->mr ) ); + ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
if( Global::iPause ) { if( Global::iPause ) {
OutText1 += " (paused)"; uitextline1 += " (paused)";
} }
if( Controlled if( Controlled
&& Controlled->Mechanik ) { && Controlled->Mechanik ) {
OutText2 = Global::Bezogonkow( Controlled->Mechanik->Relation(), true ) + " (" + tmp->Mechanik->Timetable()->TrainName + ")"; uitextline2 = Global::Bezogonkow( Controlled->Mechanik->Relation(), true ) + " (" + tmp->Mechanik->Timetable()->TrainName + ")";
if( !OutText2.empty() ) { if( !uitextline2.empty() ) {
// jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania // jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania
OutText3 = " -> " + Global::Bezogonkow( Controlled->Mechanik->NextStop(), true ); uitextline3 = " -> " + Global::Bezogonkow( Controlled->Mechanik->NextStop(), true );
} }
} }
@@ -1575,69 +1751,69 @@ TWorld::Update_UI() {
if( tmp != nullptr ) { if( tmp != nullptr ) {
// //
// jeśli domyślny ekran po pierwszym naciśnięciu // jeśli domyślny ekran po pierwszym naciśnięciu
OutText1 = "Vehicle name: " + tmp->MoverParameters->Name; uitextline1 = "Vehicle name: " + tmp->MoverParameters->Name;
if( ( tmp->Mechanik == nullptr ) && ( tmp->ctOwner ) ) { if( ( tmp->Mechanik == nullptr ) && ( tmp->ctOwner ) ) {
// for cars other than leading unit indicate the leader // for cars other than leading unit indicate the leader
OutText1 += ", owned by " + tmp->ctOwner->OwnerName(); uitextline1 += ", owned by " + tmp->ctOwner->OwnerName();
} }
// informacja o sprzęgach // informacja o sprzęgach
OutText1 += uitextline1 +=
" C0:" + " C0:" +
( tmp->PrevConnected ? ( tmp->PrevConnected ?
tmp->PrevConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 0 ].CouplingFlag ) : tmp->PrevConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 0 ].CouplingFlag ) :
"none" ); "none" );
OutText1 += uitextline1 +=
" C1:" + " C1:" +
( tmp->NextConnected ? ( tmp->NextConnected ?
tmp->NextConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 1 ].CouplingFlag ) : tmp->NextConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 1 ].CouplingFlag ) :
"none" ); "none" );
OutText2 = "Damage status: " + tmp->MoverParameters->EngineDescription( 0 ); uitextline2 = "Damage status: " + tmp->MoverParameters->EngineDescription( 0 );
OutText2 += "; Brake delay: "; uitextline2 += "; Brake delay: ";
if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_G ) == bdelay_G ) if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_G ) == bdelay_G )
OutText2 += "G"; uitextline2 += "G";
if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_P ) == bdelay_P ) if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_P ) == bdelay_P )
OutText2 += "P"; uitextline2 += "P";
if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_R ) == bdelay_R ) if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_R ) == bdelay_R )
OutText2 += "R"; uitextline2 += "R";
if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_M ) == bdelay_M ) if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_M ) == bdelay_M )
OutText2 += "+Mg"; uitextline2 += "+Mg";
OutText2 += ", BTP:" + to_string( tmp->MoverParameters->LoadFlag, 0 ); uitextline2 += ", BTP:" + to_string( tmp->MoverParameters->LoadFlag, 0 );
{ {
OutText2 += uitextline2 +=
"; pant. " "; pant. "
+ to_string( tmp->MoverParameters->PantPress, 2 ) + to_string( tmp->MoverParameters->PantPress, 2 )
+ ( tmp->MoverParameters->bPantKurek3 ? "<ZG" : "|ZG" ); + ( tmp->MoverParameters->bPantKurek3 ? "<ZG" : "|ZG" );
} }
OutText2 += uitextline2 +=
", MED:" ", MED:"
+ to_string( tmp->MoverParameters->LocalBrakePosA, 2 ) + to_string( tmp->MoverParameters->LocalBrakePosA, 2 )
+ "+" + "+"
+ to_string( tmp->MoverParameters->AnPos, 2 ); + to_string( tmp->MoverParameters->AnPos, 2 );
OutText2 += uitextline2 +=
", Ft:" ", Ft:"
+ to_string( tmp->MoverParameters->Ft * 0.001f, 0 ); + to_string( tmp->MoverParameters->Ft * 0.001f, 0 );
OutText2 += uitextline2 +=
"; TC:" "; TC:"
+ to_string( tmp->MoverParameters->TotalCurrent, 0 ); + to_string( tmp->MoverParameters->TotalCurrent, 0 );
OutText2 += uitextline2 +=
", HV0:" ", HV0:"
+ to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 1 ], 0 ) + to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 1 ], 0 )
+ "@" + "@"
+ to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 0 ], 0 ); + to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 0 ], 0 );
OutText2 += uitextline2 +=
", HV1:" ", HV1:"
+ to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 1 ], 0 ) + to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 1 ], 0 )
+ "@" + "@"
+ to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 0 ], 0 ); + to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 0 ], 0 );
OutText3 = uitextline3 =
"BP: " + to_string( tmp->MoverParameters->BrakePress, 2 ) "BP: " + to_string( tmp->MoverParameters->BrakePress, 2 )
+ " (" + to_string( tmp->MoverParameters->BrakeStatus, 0 ) + " (" + to_string( tmp->MoverParameters->BrakeStatus, 0 )
+ "), LBP: " + to_string( tmp->MoverParameters->LocBrakePress, 2 ) + "), LBP: " + to_string( tmp->MoverParameters->LocBrakePress, 2 )
@@ -1651,16 +1827,16 @@ TWorld::Update_UI() {
if( tmp->MoverParameters->ManualBrakePos > 0 ) { if( tmp->MoverParameters->ManualBrakePos > 0 ) {
OutText3 += ", manual brake on"; uitextline3 += ", manual brake on";
} }
if( tmp->MoverParameters->LocalBrakePos > 0 ) { if( tmp->MoverParameters->LocalBrakePos > 0 ) {
OutText3 += ", local brake on"; uitextline3 += ", local brake on";
} }
else { else {
OutText3 += ", local brake off"; uitextline3 += ", local brake off";
} }
if( tmp->Mechanik ) { if( tmp->Mechanik ) {
@@ -1670,9 +1846,9 @@ TWorld::Update_UI() {
if( tmp->Mechanik->DrivigFlags() & j ) // jak bit ustawiony if( tmp->Mechanik->DrivigFlags() & j ) // jak bit ustawiony
flags[ i + 1 ] = std::toupper( flags[ i + 1 ] ); // ^= 0x20; // to zmiana na wielką literę flags[ i + 1 ] = std::toupper( flags[ i + 1 ] ); // ^= 0x20; // to zmiana na wielką literę
OutText4 = flags; uitextline4 = flags;
OutText4 += uitextline4 +=
"Driver: Vd=" + to_string( tmp->Mechanik->VelDesired, 0 ) "Driver: Vd=" + to_string( tmp->Mechanik->VelDesired, 0 )
+ " ad=" + to_string( tmp->Mechanik->AccDesired, 2 ) + " ad=" + to_string( tmp->Mechanik->AccDesired, 2 )
+ " Pd=" + to_string( tmp->Mechanik->ActualProximityDist, 0 ) + " Pd=" + to_string( tmp->Mechanik->ActualProximityDist, 0 )
@@ -1684,14 +1860,14 @@ TWorld::Update_UI() {
if( ( tmp->Mechanik->VelNext == 0.0 ) if( ( tmp->Mechanik->VelNext == 0.0 )
&& ( tmp->Mechanik->eSignNext ) ) { && ( tmp->Mechanik->eSignNext ) ) {
// jeśli ma zapamiętany event semafora, nazwa eventu semafora // jeśli ma zapamiętany event semafora, nazwa eventu semafora
OutText4 += uitextline4 +=
" (" " ("
+ Global::Bezogonkow( tmp->Mechanik->eSignNext->asName ) + Global::Bezogonkow( tmp->Mechanik->eSignNext->asName )
+ ")"; + ")";
} }
// biezaca komenda dla AI // biezaca komenda dla AI
OutText4 += ", command: " + tmp->Mechanik->OrderCurrent(); uitextline4 += ", command: " + tmp->Mechanik->OrderCurrent();
} }
if( Global::iScreenMode[ Global::iTextMode - GLFW_KEY_F1 ] == 1 ) { if( Global::iScreenMode[ Global::iTextMode - GLFW_KEY_F1 ] == 1 ) {
@@ -1712,7 +1888,7 @@ TWorld::Update_UI() {
} }
else { else {
// wyświetlenie współrzędnych w scenerii oraz kąta kamery, gdy nie mamy wskaźnika // wyświetlenie współrzędnych w scenerii oraz kąta kamery, gdy nie mamy wskaźnika
OutText1 = uitextline1 =
"Camera position: " "Camera position: "
+ to_string( Camera.Pos.x, 2 ) + " " + to_string( Camera.Pos.x, 2 ) + " "
+ to_string( Camera.Pos.y, 2 ) + " " + to_string( Camera.Pos.y, 2 ) + " "
@@ -1723,8 +1899,8 @@ TWorld::Update_UI() {
+ std::string( "S SEE NEN NWW SW" ) + std::string( "S SEE NEN NWW SW" )
.substr( 0 + 2 * floor( fmod( 8 + ( Camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 ); .substr( 0 + 2 * floor( fmod( 8 + ( Camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
// current luminance level // current luminance level
OutText2 = "Light level: " + to_string( Global::fLuminance, 3 ); uitextline2 = "Light level: " + to_string( Global::fLuminance, 3 );
if( Global::FakeLight ) { OutText2 += "(*)"; } if( Global::FakeLight ) { uitextline2 += "(*)"; }
} }
break; break;
@@ -1732,13 +1908,13 @@ TWorld::Update_UI() {
case( GLFW_KEY_F8 ) : { case( GLFW_KEY_F8 ) : {
OutText1 = uitextline1 =
"Draw range x " + to_string( Global::fDistanceFactor, 1 ) "Draw range x " + to_string( Global::fDistanceFactor, 1 )
+ "; FPS: " + to_string( Timer::GetFPS(), 2 ); + "; FPS: " + to_string( Timer::GetFPS(), 2 );
if( Global::iSlowMotion ) { if( Global::iSlowMotion ) {
OutText1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")"; uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
} }
OutText1 += uitextline1 +=
", sectors: " + to_string( Ground.iRendered ) ", sectors: " + to_string( Ground.iRendered )
+ "/" + to_string( Global::iSegmentsRendered ) + "/" + to_string( Global::iSegmentsRendered )
+ "; FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 ); + "; FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 );
@@ -1748,18 +1924,12 @@ TWorld::Update_UI() {
case( GLFW_KEY_F9 ) : { case( GLFW_KEY_F9 ) : {
// informacja o wersji, sposobie wyświetlania i błędach OpenGL // informacja o wersji, sposobie wyświetlania i błędach OpenGL
OutText1 = Global::asVersion; // informacja o wersji uitextline1 = Global::asVersion; // informacja o wersji
if( Global::iMultiplayer ) { if( Global::iMultiplayer ) {
OutText1 += " (multiplayer mode is active)"; uitextline1 += " (multiplayer mode is active)";
} }
OutText2 = uitextline2 = GfxRenderer.Info();
std::string("Rendering mode: ")
+ ( Global::bUseVBO ?
"VBO" :
"Display Lists" )
+ ". "
+ GfxRenderer.Info();
// dump last opengl error, if any // dump last opengl error, if any
GLenum glerror = glGetError(); GLenum glerror = glGetError();
@@ -1767,7 +1937,7 @@ TWorld::Update_UI() {
Global::LastGLError = to_string( glerror ) + " (" + Global::Bezogonkow( (char *)gluErrorString( glerror ) ) + ")"; Global::LastGLError = to_string( glerror ) + " (" + Global::Bezogonkow( (char *)gluErrorString( glerror ) ) + ")";
} }
if( false == Global::LastGLError.empty() ) { if( false == Global::LastGLError.empty() ) {
OutText3 = uitextline3 =
"Last openGL error: " "Last openGL error: "
+ Global::LastGLError; + Global::LastGLError;
} }
@@ -1777,16 +1947,16 @@ TWorld::Update_UI() {
case( GLFW_KEY_F10 ) : { case( GLFW_KEY_F10 ) : {
OutText1 = ( "Press [Y] key to quit / Aby zakonczyc program, przycisnij klawisz [Y]." ); uitextline1 = ( "Press [Y] key to quit / Aby zakonczyc program, przycisnij klawisz [Y]." );
break; break;
} }
case( GLFW_KEY_F12 ) : { case( GLFW_KEY_F12 ) : {
// opcje włączenia i wyłączenia logowania // opcje włączenia i wyłączenia logowania
OutText1 = "[0] Debugmode " + std::string( DebugModeFlag ? "(on)" : "(off)" ); uitextline1 = "[0] Debugmode " + std::string( DebugModeFlag ? "(on)" : "(off)" );
OutText2 = "[1] log.txt " + std::string( ( Global::iWriteLogEnabled & 1 ) ? "(on)" : "(off)" ); uitextline2 = "[1] log.txt " + std::string( ( Global::iWriteLogEnabled & 1 ) ? "(on)" : "(off)" );
OutText3 = "[2] Console " + std::string( ( Global::iWriteLogEnabled & 2 ) ? "(on)" : "(off)" ); uitextline3 = "[2] Console " + std::string( ( Global::iWriteLogEnabled & 2 ) ? "(on)" : "(off)" );
break; break;
} }
@@ -1804,7 +1974,7 @@ TWorld::Update_UI() {
break; break;
} }
OutText1 = uitextline1 =
"vel: " + to_string(tmp->GetVelocity(), 2) + " km/h" "vel: " + to_string(tmp->GetVelocity(), 2) + " km/h"
+ "; dist: " + to_string(tmp->MoverParameters->DistCounter, 2) + " km" + "; dist: " + to_string(tmp->MoverParameters->DistCounter, 2) + " km"
+ "; pos: (" + "; pos: ("
@@ -1813,7 +1983,7 @@ TWorld::Update_UI() {
+ to_string( tmp->GetPosition().z, 2 ) + to_string( tmp->GetPosition().z, 2 )
+ ")"; + ")";
OutText2 = uitextline2 =
"HamZ=" + to_string( tmp->MoverParameters->fBrakeCtrlPos, 1 ) "HamZ=" + to_string( tmp->MoverParameters->fBrakeCtrlPos, 1 )
+ "; HamP=" + std::to_string( tmp->MoverParameters->LocalBrakePos ) + "/" + to_string( tmp->MoverParameters->LocalBrakePosA, 2 ) + "; HamP=" + std::to_string( tmp->MoverParameters->LocalBrakePos ) + "/" + to_string( tmp->MoverParameters->LocalBrakePosA, 2 )
+ "; NasJ=" + std::to_string( tmp->MoverParameters->MainCtrlPos ) + "(" + std::to_string( tmp->MoverParameters->MainCtrlActualPos ) + ")" + "; NasJ=" + std::to_string( tmp->MoverParameters->MainCtrlPos ) + "(" + std::to_string( tmp->MoverParameters->MainCtrlActualPos ) + ")"
@@ -1829,14 +1999,14 @@ TWorld::Update_UI() {
to_string( tmp->MoverParameters->RunningShape.R, 1 ) ) to_string( tmp->MoverParameters->RunningShape.R, 1 ) )
+ " An=" + to_string( tmp->MoverParameters->AccN, 2 ); // przyspieszenie poprzeczne + " An=" + to_string( tmp->MoverParameters->AccN, 2 ); // przyspieszenie poprzeczne
if( tprev != int( GlobalTime->mr ) ) { if( tprev != Simulation::Time.data().wSecond ) {
tprev = GlobalTime->mr; tprev = Simulation::Time.data().wSecond;
Acc = ( tmp->MoverParameters->Vel - VelPrev ) / 3.6; Acc = ( tmp->MoverParameters->Vel - VelPrev ) / 3.6;
VelPrev = tmp->MoverParameters->Vel; VelPrev = tmp->MoverParameters->Vel;
} }
OutText2 += ( "; As=" ) + to_string( Acc, 2 ); // przyspieszenie wzdłużne uitextline2 += ( "; As=" ) + to_string( Acc, 2 ); // przyspieszenie wzdłużne
OutText3 = uitextline3 =
"cyl.ham. " + to_string( tmp->MoverParameters->BrakePress, 2 ) "cyl.ham. " + to_string( tmp->MoverParameters->BrakePress, 2 )
+ "; prz.gl. " + to_string( tmp->MoverParameters->PipePress, 2 ) + "; prz.gl. " + to_string( tmp->MoverParameters->PipePress, 2 )
+ "; zb.gl. " + to_string( tmp->MoverParameters->CompressedVolume, 2 ) + "; zb.gl. " + to_string( tmp->MoverParameters->CompressedVolume, 2 )
@@ -1845,49 +2015,49 @@ TWorld::Update_UI() {
// McZapkie: warto wiedziec w jakim stanie sa przelaczniki // McZapkie: warto wiedziec w jakim stanie sa przelaczniki
if( tmp->MoverParameters->ConvOvldFlag ) if( tmp->MoverParameters->ConvOvldFlag )
OutText3 += " C! "; uitextline3 += " C! ";
else if( tmp->MoverParameters->FuseFlag ) else if( tmp->MoverParameters->FuseFlag )
OutText3 += " F! "; uitextline3 += " F! ";
else if( !tmp->MoverParameters->Mains ) else if( !tmp->MoverParameters->Mains )
OutText3 += " () "; uitextline3 += " () ";
else { else {
switch( switch(
tmp->MoverParameters->ActiveDir * tmp->MoverParameters->ActiveDir *
( tmp->MoverParameters->Imin == tmp->MoverParameters->IminLo ? ( tmp->MoverParameters->Imin == tmp->MoverParameters->IminLo ?
1 : 1 :
2 ) ) { 2 ) ) {
case 2: { OutText3 += " >> "; break; } case 2: { uitextline3 += " >> "; break; }
case 1: { OutText3 += " -> "; break; } case 1: { uitextline3 += " -> "; break; }
case 0: { OutText3 += " -- "; break; } case 0: { uitextline3 += " -- "; break; }
case -1: { OutText3 += " <- "; break; } case -1: { uitextline3 += " <- "; break; }
case -2: { OutText3 += " << "; break; } case -2: { uitextline3 += " << "; break; }
} }
} }
// McZapkie: predkosc szlakowa // McZapkie: predkosc szlakowa
if( tmp->MoverParameters->RunningTrack.Velmax == -1 ) { if( tmp->MoverParameters->RunningTrack.Velmax == -1 ) {
OutText3 += " Vtrack=Vmax"; uitextline3 += " Vtrack=Vmax";
} }
else { else {
OutText3 += " Vtrack " + to_string( tmp->MoverParameters->RunningTrack.Velmax, 2 ); uitextline3 += " Vtrack " + to_string( tmp->MoverParameters->RunningTrack.Velmax, 2 );
} }
if( ( tmp->MoverParameters->EnginePowerSource.SourceType == CurrentCollector ) if( ( tmp->MoverParameters->EnginePowerSource.SourceType == CurrentCollector )
|| ( tmp->MoverParameters->TrainType == dt_EZT ) ) { || ( tmp->MoverParameters->TrainType == dt_EZT ) ) {
OutText3 += uitextline3 +=
"; pant. " + to_string( tmp->MoverParameters->PantPress, 2 ) "; pant. " + to_string( tmp->MoverParameters->PantPress, 2 )
+ ( tmp->MoverParameters->bPantKurek3 ? "=" : "^" ) + "ZG"; + ( tmp->MoverParameters->bPantKurek3 ? "=" : "^" ) + "ZG";
} }
// McZapkie: komenda i jej parametry // McZapkie: komenda i jej parametry
if( tmp->MoverParameters->CommandIn.Command != ( "" ) ) { if( tmp->MoverParameters->CommandIn.Command != ( "" ) ) {
OutText4 = uitextline4 =
"C:" + tmp->MoverParameters->CommandIn.Command "C:" + tmp->MoverParameters->CommandIn.Command
+ " V1=" + to_string( tmp->MoverParameters->CommandIn.Value1, 0 ) + " V1=" + to_string( tmp->MoverParameters->CommandIn.Value1, 0 )
+ " V2=" + to_string( tmp->MoverParameters->CommandIn.Value2, 0 ); + " V2=" + to_string( tmp->MoverParameters->CommandIn.Value2, 0 );
} }
if( ( tmp->Mechanik ) if( ( tmp->Mechanik )
&& ( tmp->Mechanik->AIControllFlag == AIdriver ) ) { && ( tmp->Mechanik->AIControllFlag == AIdriver ) ) {
OutText4 += uitextline4 +=
"AI: Vd=" + to_string( tmp->Mechanik->VelDesired, 0 ) "AI: Vd=" + to_string( tmp->Mechanik->VelDesired, 0 )
+ " ad=" + to_string( tmp->Mechanik->AccDesired, 2 ) + " ad=" + to_string( tmp->Mechanik->AccDesired, 2 )
+ " Pd=" + to_string( tmp->Mechanik->ActualProximityDist, 0 ) + " Pd=" + to_string( tmp->Mechanik->ActualProximityDist, 0 )
@@ -1927,7 +2097,7 @@ TWorld::Update_UI() {
#ifdef EU07_USE_OLD_UI_CODE #ifdef EU07_USE_OLD_UI_CODE
if( Controlled && DebugModeFlag && !Global::iTextMode ) { if( Controlled && DebugModeFlag && !Global::iTextMode ) {
OutText1 += uitextline1 +=
( "; d_omega " ) + to_string( Controlled->MoverParameters->dizel_engagedeltaomega, 3 ); ( "; d_omega " ) + to_string( Controlled->MoverParameters->dizel_engagedeltaomega, 3 );
if( Controlled->MoverParameters->EngineType == ElectricInductionMotor ) { if( Controlled->MoverParameters->EngineType == ElectricInductionMotor ) {
@@ -1935,7 +2105,7 @@ TWorld::Update_UI() {
for( int i = 0; i <= 8; i++ ) { for( int i = 0; i <= 8; i++ ) {
for( int j = 0; j <= 9; j++ ) { for( int j = 0; j <= 9; j++ ) {
glRasterPos2f( 0.05f + 0.03f * i, 0.16f - 0.01f * j ); glRasterPos2f( 0.05f + 0.03f * i, 0.16f - 0.01f * j );
OutText4 = to_string( Train->fEIMParams[ i ][ j ], 2 ); uitextline4 = to_string( Train->fEIMParams[ i ][ j ], 2 );
} }
} }
} }
@@ -1944,12 +2114,12 @@ TWorld::Update_UI() {
// update the ui header texts // update the ui header texts
auto &headerdata = UIHeader->text_lines; auto &headerdata = UIHeader->text_lines;
headerdata[ 0 ].data = OutText1; headerdata[ 0 ].data = uitextline1;
headerdata[ 1 ].data = OutText2; headerdata[ 1 ].data = uitextline2;
headerdata[ 2 ].data = OutText3; headerdata[ 2 ].data = uitextline3;
headerdata[ 3 ].data = OutText4; headerdata[ 3 ].data = uitextline4;
{ // stenogramy dźwięków (ukryć, gdy tabelka skanowania lub rozkład?) // stenogramy dźwięków (ukryć, gdy tabelka skanowania lub rozkład?)
auto &transcripts = UITranscripts->text_lines; auto &transcripts = UITranscripts->text_lines;
transcripts.clear(); transcripts.clear();
for( auto const &transcript : Global::tranTexts.aLines ) { for( auto const &transcript : Global::tranTexts.aLines ) {
@@ -1957,14 +2127,13 @@ TWorld::Update_UI() {
if( Global::fTimeAngleDeg >= transcript.fShow ) { if( Global::fTimeAngleDeg >= transcript.fShow ) {
cParser parser( transcript.asText ); cParser parser( transcript.asText );
while( true == parser.getTokens(1, false, "|") ) { while( true == parser.getTokens( 1, false, "|" ) ) {
std::string transcriptline; parser >> transcriptline; std::string transcriptline; parser >> transcriptline;
transcripts.emplace_back( transcriptline, float4( 1.0f, 1.0f, 0.0f, 1.0f ) ); transcripts.emplace_back( transcriptline, float4( 1.0f, 1.0f, 0.0f, 1.0f ) );
} }
} }
} }
}
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -2036,15 +2205,12 @@ void TWorld::OnCommandGet(DaneRozkaz *pRozkaz)
if (*pRozkaz->iPar & 1) // ustawienie czasu if (*pRozkaz->iPar & 1) // ustawienie czasu
{ {
double t = pRozkaz->fPar[1]; double t = pRozkaz->fPar[1];
GlobalTime->dd = floor(t); // niby nie powinno być dnia, ale... Simulation::Time.data().wDay = std::floor(t); // niby nie powinno być dnia, ale...
if (Global::fMoveLight >= 0) if (Global::fMoveLight >= 0)
Global::fMoveLight = t; // trzeba by deklinację Słońca przeliczyć Global::fMoveLight = t; // trzeba by deklinację Słońca przeliczyć
GlobalTime->hh = floor(24 * t) - 24.0 * GlobalTime->dd; Simulation::Time.data().wHour = std::floor(24 * t) - 24.0 * Simulation::Time.data().wDay;
GlobalTime->mm = Simulation::Time.data().wMinute = std::floor(60 * 24 * t) - 60.0 * (24.0 * Simulation::Time.data().wDay + Simulation::Time.data().wHour);
floor(60 * 24 * t) - 60.0 * (24.0 * GlobalTime->dd + GlobalTime->hh); Simulation::Time.data().wSecond = std::floor( 60 * 60 * 24 * t ) - 60.0 * ( 60.0 * ( 24.0 * Simulation::Time.data().wDay + Simulation::Time.data().wHour ) + Simulation::Time.data().wMinute );
GlobalTime->mr =
floor(60 * 60 * 24 * t) -
60.0 * (60.0 * (24.0 * GlobalTime->dd + GlobalTime->hh) + GlobalTime->mm);
} }
if (*pRozkaz->iPar & 2) if (*pRozkaz->iPar & 2)
{ // ustawienie flag zapauzowania { // ustawienie flag zapauzowania
@@ -2333,79 +2499,88 @@ world_environment::init() {
m_skydome.init(); m_skydome.init();
m_sun.init(); m_sun.init();
m_moon.init();
m_stars.init(); m_stars.init();
m_clouds.Init(); m_clouds.Init();
} }
void
world_environment::update() {
// move sun...
m_sun.update();
auto const position = m_sun.getPosition();
// ...update the global data to match new sun state...
Global::SunAngle = m_sun.getAngle();
// ...update skydome to match the current sun position as well...
m_skydome.Update( position );
// ...retrieve current sky colour and brightness...
auto const skydomecolour = m_skydome.GetAverageColor();
auto const skydomehsv = RGBtoHSV( skydomecolour );
auto const intensity = std::min( 1.15f * (0.05f + m_sun.getIntensity() + skydomehsv.z), 1.25f );
// ...update light colours and intensity.
// NOTE: intensity combines intensity of the sun and the light reflected by the sky dome
// it'd be more technically correct to have just the intensity of the sun here,
// but whether it'd _look_ better is something to be tested
Global::daylight.position = float3(position.x, position.y, position.z);
vector3 sun = -1.0 * m_sun.getDirection();
Global::daylight.direction = float3(sun.x, sun.y, sun.z);
Global::daylight.color = float3(intensity * 255.0f / 255.0f,
intensity * 242.0f / 255.0f,
intensity * 231.0f / 255.0f);
Global::daylight.ambient = float3(skydomecolour.x, skydomecolour.y, skydomecolour.z);
// update the fog. setting it to match the average colour of the sky dome is cheap
// but quite effective way to make the distant items blend with background better
Global::FogColor[ 0 ] = skydomecolour.x;
Global::FogColor[ 1 ] = skydomecolour.y;
Global::FogColor[ 2 ] = skydomecolour.z;
::glFogfv( GL_FOG_COLOR, Global::FogColor ); // kolor mgły
::glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f ); // kolor nieba
}
extern TWorld World; extern TWorld World;
void void
world_environment::render() { world_environment::update() {
// move celestial bodies...
GfxRenderer.Bind( 0 ); m_sun.update();
m_moon.update();
::glDisable( GL_LIGHTING ); // ...determine source of key light and adjust global state accordingly...
::glDisable( GL_FOG ); auto const sunlightlevel = m_sun.getIntensity();
::glDisable( GL_DEPTH_TEST ); auto const moonlightlevel = m_moon.getIntensity();
::glDepthMask( GL_FALSE ); float keylightintensity;
::glPushMatrix(); float twilightfactor;
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z ); float3 keylightcolor;
if (moonlightlevel > sunlightlevel) {
m_skydome.Render(); // rare situations when the moon is brighter than the sun, typically at night
m_stars.render(); Global::SunAngle = m_moon.getAngle();
m_clouds.Render( m_skydome.GetAverageColor() * 2.5f ); Math3D::vector3 moon_dir = -1.0 * m_moon.getDirection();
Global::daylight.direction = glm::vec3(moon_dir.x, moon_dir.y, moon_dir.z);
if( DebugModeFlag == true ) { keylightintensity = moonlightlevel;
// mark sun position for easier debugging // if the moon is up, it overrides the twilight
m_sun.render(); twilightfactor = 0.0f;
keylightcolor = float3(255.0f / 255.0f, 242.0f / 255.0f, 202.0f / 255.0f);
} }
else {
// regular situation with sun as the key light
Global::SunAngle = m_sun.getAngle();
Math3D::vector3 sun_dir = -1.0 * m_sun.getDirection();
Global::daylight.direction = glm::vec3(sun_dir.x, sun_dir.y, sun_dir.z);
keylightintensity = sunlightlevel;
// diffuse (sun) intensity goes down after twilight, and reaches minimum 18 degrees below horizon
twilightfactor = clamp(-Global::SunAngle, 0.0f, 18.0f) / 18.0f;
// TODO: crank orange up at dawn/dusk
keylightcolor = float3(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f);
float const duskfactor = 1.0f - clamp(Global::SunAngle, 0.0f, 18.0f) / 18.0f;
keylightcolor = interpolate(
float3(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f),
float3(235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f),
duskfactor);
}
// ...update skydome to match the current sun position as well...
m_skydome.SetOvercastFactor(Global::Overcast);
m_skydome.Update(m_sun.getPosition());
// ...retrieve current sky colour and brightness...
auto const skydomecolour = m_skydome.GetAverageColor();
auto const skydomehsv = RGBtoHSV(skydomecolour);
// sun strength is reduced by overcast level
keylightintensity *= (1.0f - Global::Overcast * 0.65f);
World.shader.set_ambient(Global::daylight.ambient); // intensity combines intensity of the sun and the light reflected by the sky dome
World.shader.set_light(0, gl_program_light::DIR, Global::daylight.position, Global::daylight.direction, // it'd be more technically correct to have just the intensity of the sun here,
0.0f, 0.0f, Global::daylight.color * Global::daylight.intensity, 0.0f, 0.0f); // but whether it'd _look_ better is something to be tested
auto const intensity = std::min(1.15f * (0.05f + keylightintensity + skydomehsv.z), 1.25f);
// the impact of sun component is reduced proportionally to overcast level, as overcast increases role of ambient light
auto const diffuselevel = interpolate(keylightintensity, intensity * (1.0f - twilightfactor), 1.0f - Global::Overcast * 0.75f);
// ...update light colours and intensity.
keylightcolor = keylightcolor * diffuselevel;
Global::daylight.color.x = keylightcolor.x;
Global::daylight.color.y = keylightcolor.y;
Global::daylight.color.z = keylightcolor.z;
::glPopMatrix(); // tonal impact of skydome color is inversely proportional to how high the sun is above the horizon
::glDepthMask( GL_TRUE ); // (this is pure conjecture, aimed more to 'look right' than be accurate)
::glEnable( GL_DEPTH_TEST ); float const ambienttone = clamp(1.0f - (Global::SunAngle / 90.0f), 0.0f, 1.0f);
::glEnable( GL_FOG ); Global::daylight.ambient.x = interpolate(skydomehsv.z, skydomecolour.x, ambienttone);
::glEnable( GL_LIGHTING ); Global::daylight.ambient.y = interpolate(skydomehsv.z, skydomecolour.y, ambienttone);
Global::daylight.ambient.z = interpolate(skydomehsv.z, skydomecolour.z, ambienttone);
Global::fLuminance = intensity;
// update the fog. setting it to match the average colour of the sky dome is cheap
// but quite effective way to make the distant items blend with background better
Global::FogColor[0] = skydomecolour.x;
Global::FogColor[1] = skydomecolour.y;
Global::FogColor[2] = skydomecolour.z;
::glFogfv(GL_FOG_COLOR, Global::FogColor); // kolor mgły
::glClearColor(skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f); // kolor nieba
} }
void void

68
World.h
View File

@@ -15,24 +15,65 @@ http://mozilla.org/MPL/2.0/.
#include "Ground.h" #include "Ground.h"
#include "sky.h" #include "sky.h"
#include "sun.h" #include "sun.h"
#include "moon.h"
#include "stars.h" #include "stars.h"
#include "skydome.h" #include "skydome.h"
#include "mczapkie/mover.h" #include "mczapkie/mover.h"
#include "renderer.h"
// wrapper for simulation time
class simulation_time {
public:
simulation_time() { m_time.wHour = 10; m_time.wMinute = 30; }
void
init();
void
update( double const Deltatime );
SYSTEMTIME &
data() { return m_time; }
SYSTEMTIME const &
data() const { return m_time; }
double
second() const { return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); }
int
year_day() const { return m_yearday; }
int
julian_day() const;
private:
// calculates day of year from given date
int
yearday( int Day, int const Month, int const Year );
// calculates day and month from given day of year
void
daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
SYSTEMTIME m_time;
int m_yearday;
char m_monthdaycounts[ 2 ][ 13 ];
};
namespace Simulation {
extern simulation_time Time;
}
// wrapper for environment elements -- sky, sun, stars, clouds etc // wrapper for environment elements -- sky, sun, stars, clouds etc
class world_environment { class world_environment {
friend opengl_renderer;
public: public:
void init(); void init();
void update(); void update();
void render();
void time( int const Hour = -1, int const Minute = -1, int const Second = -1 ); void time( int const Hour = -1, int const Minute = -1, int const Second = -1 );
private: private:
CSkyDome m_skydome; CSkyDome m_skydome;
cStars m_stars; cStars m_stars;
cSun m_sun; cSun m_sun;
cMoon m_moon;
TSky m_clouds; TSky m_clouds;
}; };
@@ -45,11 +86,19 @@ class TWorld
void FollowView(bool wycisz = true); void FollowView(bool wycisz = true);
void DistantView( bool const Near = false ); void DistantView( bool const Near = false );
public: public:
// types
// constructors
TWorld();
// destructor
~TWorld();
// methods
bool Init( GLFWwindow *w ); bool Init( GLFWwindow *w );
bool InitPerformed() { return m_init; } bool InitPerformed() { return m_init; }
GLFWwindow *window; GLFWwindow *window;
GLvoid glPrint(std::string const &Text);
void OnKeyDown(int cKey); void OnKeyDown(int cKey);
void OnKeyUp(int cKey); void OnKeyUp(int cKey);
// void UpdateWindow(); // void UpdateWindow();
@@ -59,19 +108,14 @@ class TWorld
void TrainDelete(TDynamicObject *d = NULL); void TrainDelete(TDynamicObject *d = NULL);
// switches between static and dynamic daylight calculation // switches between static and dynamic daylight calculation
void ToggleDaylight(); void ToggleDaylight();
TWorld();
~TWorld(); private:
// double Aspect;
private:
std::string OutText1; // teksty na ekranie
std::string OutText2;
std::string OutText3;
std::string OutText4;
void Update_Environment(); void Update_Environment();
void Update_Camera( const double Deltatime ); void Update_Camera( const double Deltatime );
void Update_UI(); void Update_UI();
void ResourceSweep(); void ResourceSweep();
void Render_Cab(); void Render_Cab();
TCamera Camera; TCamera Camera;
TGround Ground; TGround Ground;
world_environment Environment; world_environment Environment;

View File

@@ -139,14 +139,15 @@ class matrix4x4
// the column increasing fastest. However, some APIs (OpenGL in particular) do this // the column increasing fastest. However, some APIs (OpenGL in particular) do this
// backwards, hence the "constructor" from C matrices, or from OpenGL matrices. // backwards, hence the "constructor" from C matrices, or from OpenGL matrices.
// Note that matrices are stored internally in OpenGL format. // Note that matrices are stored internally in OpenGL format.
void C_Matrix(scalar_t *initArray) void C_Matrix(scalar_t const *initArray)
{ {
int i = 0; int i = 0;
for (int y = 0; y < 4; ++y) for (int y = 0; y < 4; ++y)
for (int x = 0; x < 4; ++x) for (int x = 0; x < 4; ++x)
(*this)(x)[y] = initArray[i++]; (*this)(x)[y] = initArray[i++];
} }
void OpenGL_Matrix(scalar_t *initArray) template <typename _Type>
void OpenGL_Matrix(_Type const *initArray)
{ {
int i = 0; int i = 0;
for (int x = 0; x < 4; ++x) for (int x = 0; x < 4; ++x)

View File

@@ -11,10 +11,19 @@ http://mozilla.org/MPL/2.0/.
#include "frustum.h" #include "frustum.h"
void void
cFrustum::calculate( glm::mat4 &Projection, glm::mat4 &Modelview ) { cFrustum::calculate() {
float *proj = &Projection[ 0 ][ 0 ]; auto const &projection = OpenGLMatrices.data( GL_PROJECTION );
float *modl = &Modelview[ 0 ][ 0 ]; auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
calculate( projection, modelview );
}
void
cFrustum::calculate( glm::mat4 const &Projection, glm::mat4 const &Modelview ) {
float const *proj = &Projection[ 0 ][ 0 ];
float const *modl = &Modelview[ 0 ][ 0 ];
float clip[ 16 ]; float clip[ 16 ];
// multiply the matrices to retrieve clipping planes // multiply the matrices to retrieve clipping planes

View File

@@ -22,7 +22,9 @@ public:
// methods: // methods:
// update the frustum to match current view orientation // update the frustum to match current view orientation
void void
calculate(glm::mat4 &Projection, glm::mat4 &Modelview); calculate();
void
calculate(glm::mat4 const &Projection, glm::mat4 const &Modelview);
// returns true if specified point is inside of the frustum // returns true if specified point is inside of the frustum
inline inline
bool bool

View File

@@ -73,16 +73,18 @@ light_array::update() {
else { else {
light.intensity = 0.0f; light.intensity = 0.0f;
} }
/*
// crude catch for unmanned modules which share the light state with the controlled unit. // crude catch for unmanned modules which share the light state with the controlled unit.
// why don't they get their own light bits btw ._. // why don't they get their own light bits btw ._.
// TODO, TBD: have separate light bits for each vehicle, so this override isn't necessary // TODO, TBD: have separate light bits for each vehicle, so this override isn't necessary
// NOTE: should be no longer needed, test and delete if there's no ill effects
if( ( light.owner->Controller == AIdriver ) if( ( light.owner->Controller == AIdriver )
&& ( light.owner->Mechanik == nullptr ) ) { && ( light.owner->Mechanik == nullptr ) ) {
light.intensity = 0.0f; light.intensity = 0.0f;
light.count = 0; light.count = 0;
} }
*/
} }
else { else {
// with battery off the lights are off // with battery off the lights are off

325
moon.cpp Normal file
View File

@@ -0,0 +1,325 @@
#include "stdafx.h"
#include "moon.h"
#include "globals.h"
#include "mtable.h"
#include "usefull.h"
#include "world.h"
//////////////////////////////////////////////////////////////////////////////////////////
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
cMoon::cMoon() {
setLocation( 19.00f, 52.00f ); // default location roughly in centre of Poland
m_observer.press = 1013.0; // surface pressure, millibars
m_observer.temp = 15.0; // ambient dry-bulb temperature, degrees C
TIME_ZONE_INFORMATION timezoneinfo; // TODO: timezone dependant on geographic location
::GetTimeZoneInformation( &timezoneinfo );
m_observer.timezone = -timezoneinfo.Bias / 60.0f;
}
cMoon::~cMoon() { gluDeleteQuadric( moonsphere ); }
void
cMoon::init() {
moonsphere = gluNewQuadric();
gluQuadricNormals( moonsphere, GLU_SMOOTH );
// NOTE: we're calculating phase just once, because it's unlikely simulation will last a few days,
// plus a sudden texture change would be pretty jarring
phase();
}
void
cMoon::update() {
move();
Math3D::vector3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor );
position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) );
position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) );
m_position = position;
}
void
cMoon::render() {
glColor4f( 225.0f/255.0f, 225.0f/255.0f, 255.0f/255.0f, 1.f );
// debug line to locate the sun easier
Math3D::vector3 position = m_position;
glBegin( GL_LINES );
glVertex3f( position.x, position.y, position.z );
glVertex3f( position.x, 0.0f, position.z );
glEnd();
glPushMatrix();
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 );
glPopMatrix();
}
Math3D::vector3
cMoon::getDirection() {
Math3D::vector3 position( 0.f, 0.f, -1.f );
position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) );
position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) );
position.Normalize();
return position;
}
float
cMoon::getAngle() const {
return (float)m_body.elevref;
}
float cMoon::getIntensity() {
irradiance();
// NOTE: we don't have irradiance model for the moon so we cheat here
// calculating intensity of the sun instead, and returning 15% of the value,
// which roughly matches how much sunlight is reflected by the moon
// We alter the intensity further based on current phase of the moon
auto const phasefactor = 1.0f - std::abs( m_phase - 29.53f * 0.5f ) / ( 29.53 * 0.5f );
return (float)( m_body.etr/ 1399.0 ) * phasefactor * 0.15f; // arbitrary scaling factor taken from etrn value
}
void cMoon::setLocation( float const Longitude, float const Latitude ) {
// convert fraction from geographical base of 6o minutes
m_observer.longitude = (int)Longitude + (Longitude - (int)(Longitude)) * 100.0 / 60.0;
m_observer.latitude = (int)Latitude + (Latitude - (int)(Latitude)) * 100.0 / 60.0 ;
}
// sets current time, overriding one acquired from the system clock
void cMoon::setTime( int const Hour, int const Minute, int const Second ) {
m_observer.hour = clamp( Hour, -1, 23 );
m_observer.minute = clamp( Minute, -1, 59 );
m_observer.second = clamp( Second, -1, 59 );
}
void cMoon::setTemperature( float const Temperature ) {
m_observer.temp = Temperature;
}
void cMoon::setPressure( float const Pressure ) {
m_observer.press = Pressure;
}
void cMoon::move() {
static double radtodeg = 57.295779513; // converts from radians to degrees
static double degtorad = 0.0174532925; // converts from degrees to radians
SYSTEMTIME localtime = Simulation::Time.data(); // time for the calculation
if( m_observer.hour >= 0 ) { localtime.wHour = m_observer.hour; }
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; }
double ut = localtime.wHour
+ localtime.wMinute / 60.0 // too low resolution, noticeable skips
+ localtime.wSecond / 3600.0; // good enough in normal circumstances
/*
+ localtime.wMilliseconds / 3600000.0; // for really smooth movement
*/
double daynumber = 367 * localtime.wYear
- 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4
+ 275 * localtime.wMonth / 9
+ localtime.wDay
- 730530
+ ( ut / 24.0 );
// Universal Coordinated (Greenwich standard) time
m_observer.utime = ut * 3600.0;
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
// obliquity of the ecliptic
m_body.oblecl = clamp_circular( 23.4393 - 3.563e-7 * daynumber );
// moon parameters
double longascnode = clamp_circular( 125.1228 - 0.0529538083 * daynumber ); // N, degrees
double const inclination = 5.1454; // i, degrees
double const mndistance = 60.2666; // a, in earth radii
// argument of perigee
double const perigeearg = clamp_circular( 318.0634 + 0.1643573223 * daynumber ); // w, degrees
// mean anomaly
m_body.mnanom = clamp_circular( 115.3654 + 13.0649929509 * daynumber ); // M, degrees
// eccentricity
double const e = 0.054900;
// eccentric anomaly
double E0 = m_body.mnanom + radtodeg * e * std::sin( degtorad * m_body.mnanom ) * ( 1.0 + e * std::cos( degtorad * m_body.mnanom ) );
double E1 = E0 - ( E0 - radtodeg * e * std::sin( degtorad * E0 ) - m_body.mnanom ) / ( 1.0 - e * std::cos( degtorad * E0 ) );
while( std::abs( E0 - E1 ) > 0.005 ) { // arbitrary precision tolerance threshold
E0 = E1;
E1 = E0 - ( E0 - radtodeg * e * std::sin( degtorad * E0 ) - m_body.mnanom ) / ( 1.0 - e * std::cos( degtorad * E0 ) );
}
double const E = E1;
// lunar orbit plane rectangular coordinates
double const xv = mndistance * ( std::cos( degtorad * E ) - e );
double const yv = mndistance * std::sin( degtorad * E ) * std::sqrt( 1.0 - e*e );
// distance
m_body.distance = std::sqrt( xv*xv + yv*yv ); // r
// true anomaly
m_body.tranom = clamp_circular( radtodeg * std::atan2( yv, xv ) ); // v
// ecliptic rectangular coordinates
double const vpluswinrad = degtorad * ( m_body.tranom + perigeearg );
double const xeclip = m_body.distance * ( std::cos( degtorad * longascnode ) * std::cos( vpluswinrad ) - std::sin( degtorad * longascnode ) * std::sin( vpluswinrad ) * std::cos( degtorad * inclination ) );
double const yeclip = m_body.distance * ( std::sin( degtorad * longascnode ) * std::cos( vpluswinrad ) + std::cos( degtorad * longascnode ) * std::sin( vpluswinrad ) * std::cos( degtorad * inclination ) );
double const zeclip = m_body.distance * std::sin( vpluswinrad ) * std::sin( degtorad * inclination );
// ecliptic coordinates
double ecliplat = radtodeg * std::atan2( zeclip, std::sqrt( xeclip*xeclip + yeclip*yeclip ) );
m_body.eclong = clamp_circular( radtodeg * std::atan2( yeclip, xeclip ) );
// distance
m_body.distance = std::sqrt( xeclip*xeclip + yeclip*yeclip + zeclip*zeclip );
// perturbations
// NOTE: perturbation calculation can be safely disabled if we don't mind error of 1-2 degrees
// Sun's mean anomaly: Ms (already computed)
double const sunmnanom = clamp_circular( 356.0470 + 0.9856002585 * daynumber ); // M
// Sun's mean longitude: Ls (already computed)
double const sunphlong = clamp_circular( 282.9404 + 4.70935e-5 * daynumber );
double const sunmnlong = clamp_circular( sunphlong + sunmnanom ); // L = w + M
// Moon's mean anomaly: Mm (already computed)
// Moon's mean longitude: Lm = N + w + M (for the Moon)
m_body.mnlong = clamp_circular( longascnode + perigeearg + m_body.mnanom );
// Moon's mean elongation: D = Lm - Ls
double const mnelong = clamp_circular( m_body.mnlong - sunmnlong );
// Moon's argument of latitude: F = Lm - N
double const arglat = clamp_circular( m_body.mnlong - longascnode );
// longitude perturbations
double const pertevection = -1.274 * std::sin( degtorad * ( m_body.mnanom - 2.0 * mnelong ) ); // Evection
double const pertvariation = +0.658 * std::sin( degtorad * ( 2.0 * mnelong ) ); // Variation
double const pertyearlyeqt = -0.186 * std::sin( degtorad * sunmnanom ); // Yearly equation
// latitude perturbations
double const pertlat = -0.173 * std::sin( degtorad * ( arglat - 2.0 * mnelong ) );
m_body.eclong += pertevection + pertvariation + pertyearlyeqt;
ecliplat += pertlat;
// declination
m_body.declin = radtodeg * std::asin( std::sin (m_body.oblecl * degtorad) * std::sin(m_body.eclong * degtorad) );
// right ascension
double top = std::cos( degtorad * m_body.oblecl ) * std::sin( degtorad * m_body.eclong );
double bottom = std::cos( degtorad * m_body.eclong );
m_body.rascen = clamp_circular( radtodeg * std::atan2( top, bottom ) );
// Greenwich mean sidereal time
m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime;
m_observer.gmst -= 24.0 * (int)( m_observer.gmst / 24.0 );
if( m_observer.gmst < 0.0 ) m_observer.gmst += 24.0;
// local mean sidereal time
m_observer.lmst = m_observer.gmst * 15.0 + m_observer.longitude;
m_observer.lmst -= 360.0 * (int)( m_observer.lmst / 360.0 );
if( m_observer.lmst < 0.0 ) m_observer.lmst += 360.0;
// hour angle
m_body.hrang = m_observer.lmst - m_body.rascen;
if( m_body.hrang < -180.0 ) m_body.hrang += 360.0; // (force it between -180 and 180 degrees)
else if( m_body.hrang > 180.0 ) m_body.hrang -= 360.0;
double cz; // cosine of the solar zenith angle
double tdatcd = std::cos( degtorad * m_body.declin );
double tdatch = std::cos( degtorad * m_body.hrang );
double tdatcl = std::cos( degtorad * m_observer.latitude );
double tdatsd = std::sin( degtorad * m_body.declin );
double tdatsl = std::sin( degtorad * m_observer.latitude );
cz = tdatsd * tdatsl + tdatcd * tdatcl * tdatch;
// (watch out for the roundoff errors)
if( fabs (cz) > 1.0 ) { cz >= 0.0 ? cz = 1.0 : cz = -1.0; }
m_body.zenetr = std::acos( cz ) * radtodeg;
m_body.elevetr = 90.0 - m_body.zenetr;
refract();
}
void cMoon::refract() {
static double degtorad = 0.0174532925; // converts from degrees to radians
double prestemp; // temporary pressure/temperature correction
double refcor; // temporary refraction correction
double tanelev; // tangent of the solar elevation angle
// if the sun is near zenith, the algorithm bombs; refraction near 0.
if( m_body.elevetr > 85.0 )
refcor = 0.0;
else {
tanelev = tan( degtorad * m_body.elevetr );
if( m_body.elevetr >= 5.0 )
refcor = 58.1 / tanelev
- 0.07 / pow( tanelev, 3 )
+ 0.000086 / pow( tanelev, 5 );
else if( m_body.elevetr >= -0.575 )
refcor = 1735.0
+ m_body.elevetr * ( -518.2 + m_body.elevetr *
( 103.4 + m_body.elevetr * ( -12.79 + m_body.elevetr * 0.711 ) ) );
else
refcor = -20.774 / tanelev;
prestemp = ( m_observer.press * 283.0 ) / ( 1013.0 * ( 273.0 + m_observer.temp ) );
refcor *= prestemp / 3600.0;
}
// refracted solar elevation angle
m_body.elevref = m_body.elevetr + refcor;
// refracted solar zenith angle
m_body.zenref = 90.0 - m_body.elevref;
}
void cMoon::irradiance() {
static double radtodeg = 57.295779513; // converts from radians to degrees
static double degtorad = 0.0174532925; // converts from degrees to radians
m_body.dayang = ( Simulation::Time.year_day() - 1 ) * 360.0 / 365.0;
double sd = sin( degtorad * m_body.dayang ); // sine of the day angle
double cd = cos( degtorad * m_body.dayang ); // cosine of the day angle or delination
m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd;
double d2 = 2.0 * m_body.dayang;
double c2 = cos( degtorad * d2 );
double s2 = sin( degtorad * d2 );
m_body.erv += 0.000719*c2 + 0.000077*s2;
double solcon = 1367.0; // Solar constant, 1367 W/sq m
m_body.coszen = cos( degtorad * m_body.zenref );
if( m_body.coszen > 0.0 ) {
m_body.etrn = solcon * m_body.erv;
m_body.etr = m_body.etrn * m_body.coszen;
}
else {
m_body.etrn = 0.0;
m_body.etr = 0.0;
}
}
void
cMoon::phase() {
// calculate moon's age in days from new moon
float ip = normalize( ( Simulation::Time.julian_day() - 2451550.1f ) / 29.530588853f );
m_phase = ip * 29.53f;
}
// normalize values to range 0...1
float
cMoon::normalize( const float Value ) const {
float value = Value - floor( Value );
if( value < 0.f ) { ++value; }
return value;
}

106
moon.h Normal file
View File

@@ -0,0 +1,106 @@
#pragma once
#include "windows.h"
#include "GL/glew.h"
#include "GL/wglew.h"
#include "dumb3d.h"
// TODO: sun and moon share code as celestial bodies, we could make a base class out of it
class cMoon {
public:
// types:
// methods:
void init();
void update();
void render();
// returns location of the sun in the 3d scene
Math3D::vector3 getPosition() { return m_position; }
// returns vector pointing at the sun
Math3D::vector3 getDirection();
// returns current elevation above horizon
float getAngle() const;
// returns current intensity of the sun
float getIntensity();
// returns current phase of the moon
float getPhase() const { return m_phase; }
// sets current time, overriding one acquired from the system clock
void setTime( int const Hour, int const Minute, int const Second );
// sets current geographic location
void setLocation( float const Longitude, float const Latitude );
// sets ambient temperature in degrees C.
void setTemperature( float const Temperature );
// sets surface pressure in milibars
void setPressure( float const Pressure );
// constructors:
cMoon();
// deconstructor:
~cMoon();
// members:
protected:
// types:
// methods:
// calculates sun position on the sky given specified time and location
void move();
// calculates position adjustment due to refraction
void refract();
// calculates light intensity at current moment
void irradiance();
void phase();
// helper, normalize values to range 0...1
float normalize( const float Value ) const;
// members:
GLUquadricObj *moonsphere; // temporary handler for moon positioning test
struct celestialbody { // main planet parameters
double dayang; // day angle (daynum*360/year-length) degrees
double phlong; // longitude of perihelion
double mnlong; // mean longitude, degrees
double mnanom; // mean anomaly, degrees
double tranom; // true anomaly, degrees
double eclong; // ecliptic longitude, degrees.
double oblecl; // obliquity of ecliptic.
double declin; // declination--zenith angle of solar noon at equator, degrees NORTH.
double rascen; // right ascension, degrees
double hrang; // hour angle--hour of sun from solar noon, degrees WEST
double zenetr; // solar zenith angle, no atmospheric correction (= ETR)
double zenref; // solar zenith angle, deg. from zenith, refracted
double coszen; // cosine of refraction corrected solar zenith angle
double elevetr; // solar elevation, no atmospheric correction (= ETR)
double elevref; // solar elevation angle, deg. from horizon, refracted.
double distance; // distance from earth in AUs
double erv; // earth radius vector (multiplied to solar constant)
double etr; // extraterrestrial (top-of-atmosphere) W/sq m global horizontal solar irradiance
double etrn; // extraterrestrial (top-of-atmosphere) W/sq m direct normal solar irradiance
};
struct observer { // weather, time and position data in observer's location
double latitude; // latitude, degrees north (south negative)
double longitude; // longitude, degrees east (west negative)
int hour{ -1 }; // current time, used for calculation of utime. if set to -1, time for
int minute{ -1 };// calculation will be obtained from the local clock
int second{ -1 };
double utime; // universal (Greenwich) standard time
double timezone; // time zone, east (west negative). USA: Mountain = -7, Central = -6, etc.
double gmst; // Greenwich mean sidereal time, hours
double lmst; // local mean sidereal time, degrees
double temp; // ambient dry-bulb temperature, degrees C, used for refraction correction
double press; // surface pressure, millibars, used for refraction correction and ampress
};
celestialbody m_body;
observer m_observer;
Math3D::vector3 m_position;
float m_phase;
};

View File

@@ -1,7 +1,3 @@
/** @file
@brief
*/
/* /*
This Source Code Form is subject to the This Source Code Form is subject to the
terms of the Mozilla Public License, v. terms of the Mozilla Public License, v.
@@ -15,9 +11,6 @@ http://mozilla.org/MPL/2.0/.
#include "mtable.h" #include "mtable.h"
#include "mczapkie/mctools.h" #include "mczapkie/mctools.h"
// using namespace Mtable;
std::shared_ptr<TMTableTime> Mtable::GlobalTime;
double CompareTime(double t1h, double t1m, double t2h, double t2m) /*roznica czasu w minutach*/ double CompareTime(double t1h, double t1m, double t2h, double t2m) /*roznica czasu w minutach*/
// zwraca różnicę czasu // zwraca różnicę czasu
// jeśli pierwsza jest aktualna, a druga rozkładowa, to ujemna oznacza opóżnienie // jeśli pierwsza jest aktualna, a druga rozkładowa, to ujemna oznacza opóżnienie
@@ -73,7 +66,12 @@ bool TTrainParameters::IsStop()
return true; // na ostatnim się zatrzymać zawsze return true; // na ostatnim się zatrzymać zawsze
} }
bool TTrainParameters::UpdateMTable(double hh, double mm, std::string NewName) bool TTrainParameters::UpdateMTable( simulation_time const &Time, std::string const &NewName ) {
return UpdateMTable( Time.data().wHour, Time.data().wMinute, NewName );
}
bool TTrainParameters::UpdateMTable(double hh, double mm, std::string const &NewName)
/*odfajkowanie dojechania do stacji (NewName) i przeliczenie opóźnienia*/ /*odfajkowanie dojechania do stacji (NewName) i przeliczenie opóźnienia*/
{ {
bool OK; bool OK;
@@ -138,13 +136,13 @@ std::string TTrainParameters::ShowRelation()
return ""; return "";
} }
TTrainParameters::TTrainParameters(std::string NewTrainName) TTrainParameters::TTrainParameters(std::string const &NewTrainName)
/*wstępne ustawienie parametrów rozkładu jazdy*/ /*wstępne ustawienie parametrów rozkładu jazdy*/
{ {
NewName(NewTrainName); NewName(NewTrainName);
} }
void TTrainParameters::NewName(std::string NewTrainName) void TTrainParameters::NewName(std::string const &NewTrainName)
/*wstępne ustawienie parametrów rozkładu jazdy*/ /*wstępne ustawienie parametrów rozkładu jazdy*/
{ {
TrainName = NewTrainName; TrainName = NewTrainName;
@@ -519,30 +517,29 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
void TMTableTime::UpdateMTableTime(double deltaT) void TMTableTime::UpdateMTableTime(double deltaT)
// dodanie czasu (deltaT) w sekundach, z przeliczeniem godziny // dodanie czasu (deltaT) w sekundach, z przeliczeniem godziny
{ {
mr = mr + deltaT; // dodawanie sekund mr += deltaT; // dodawanie sekund
while (mr > 60.0) // przeliczenie sekund do właściwego przedziału while (mr >= 60.0) // przeliczenie sekund do właściwego przedziału
{ {
mr = mr - 60.0; mr -= 60.0;
++mm; ++mm;
} }
while (mm > 59) // przeliczenie minut do właściwego przedziału while (mm > 59) // przeliczenie minut do właściwego przedziału
{ {
mm = mm - 60; mm -= 60;
++hh; ++hh;
} }
while (hh > 23) // przeliczenie godzin do właściwego przedziału while (hh > 23) // przeliczenie godzin do właściwego przedziału
{ {
hh = hh - 24; hh -= 24;
++dd; // zwiększenie numeru dnia ++dd; // zwiększenie numeru dnia
} }
GameTime = GameTime + deltaT;
} }
bool TTrainParameters::DirectionChange() bool TTrainParameters::DirectionChange()
// sprawdzenie, czy po zatrzymaniu wykonać kolejne komendy // sprawdzenie, czy po zatrzymaniu wykonać kolejne komendy
{ {
if ((StationIndex > 0) && (StationIndex < StationCount)) // dla ostatniej stacji nie if ((StationIndex > 0) && (StationIndex < StationCount)) // dla ostatniej stacji nie
if (TimeTable[StationIndex].StationWare.find("@") != std::string::npos) if (TimeTable[StationIndex].StationWare.find('@') != std::string::npos)
return true; return true;
return false; return false;
} }

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#pragma once #pragma once
#include <string> #include <string>
#include "world.h"
namespace Mtable namespace Mtable
{ {
@@ -73,9 +74,10 @@ class TTrainParameters
std::string NextStop(); std::string NextStop();
bool IsStop(); bool IsStop();
bool IsTimeToGo(double hh, double mm); bool IsTimeToGo(double hh, double mm);
bool UpdateMTable(double hh, double mm, std::string NewName); bool UpdateMTable(double hh, double mm, std::string const &NewName);
TTrainParameters(std::string NewTrainName); bool UpdateMTable( simulation_time const &Time, std::string const &NewName );
void NewName(std::string NewTrainName); TTrainParameters( std::string const &NewTrainName );
void NewName(std::string const &NewTrainName);
void UpdateVelocity(int StationCount, double vActual); void UpdateVelocity(int StationCount, double vActual);
bool LoadTTfile(std::string scnpath, int iPlus, double vmax); bool LoadTTfile(std::string scnpath, int iPlus, double vmax);
bool DirectionChange(); bool DirectionChange();
@@ -86,29 +88,19 @@ class TMTableTime
{ {
public: public:
double GameTime = 0.0;
int dd = 0; int dd = 0;
int hh = 0; int hh = 0;
int mm = 0; int mm = 0;
int srh = 0;
int srm = 0; /*wschod slonca*/
int ssh = 0;
int ssm = 0; /*zachod slonca*/
double mr = 0.0; double mr = 0.0;
void UpdateMTableTime(double deltaT); void UpdateMTableTime(double deltaT);
TMTableTime(int InitH, int InitM, int InitSRH, int InitSRM, int InitSSH, int InitSSM) : TMTableTime(int InitH, int InitM ) :
hh( InitH ), hh( InitH ),
mm( InitM ), mm( InitM )
srh( InitSRH ),
srm( InitSRM ),
ssh( InitSSH ),
ssm( InitSSM )
{} {}
TMTableTime() = default; TMTableTime() = default;
}; };
extern std::shared_ptr<TMTableTime> GlobalTime;
} }
#if !defined(NO_IMPLICIT_NAMESPACE_USE) #if !defined(NO_IMPLICIT_NAMESPACE_USE)

13
openglmatrixstack.cpp Normal file
View File

@@ -0,0 +1,13 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "openglmatrixstack.h"
opengl_matrices OpenGLMatrices;

183
openglmatrixstack.h Normal file
View File

@@ -0,0 +1,183 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <stack>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "GL/glew.h"
#ifdef _WINDOWS
#include "GL/wglew.h"
#endif
// encapsulation of the fixed pipeline opengl matrix stack
class opengl_matrices {
// types:
class opengl_stack {
public:
// constructors:
opengl_stack() { m_stack.emplace(1.0f); }
// methods:
glm::mat4 const &
data() const { return m_stack.top(); }
void
push_matrix() { m_stack.emplace(m_stack.top()); }
void
pop_matrix() {
m_stack.pop();
if( m_stack.empty() ) { m_stack.emplace(1.0f); }
upload(); }
void
load_identity() {
m_stack.top() = glm::mat4( 1.0f );
upload(); }
void
rotate( float const Angle, glm::vec3 const &Axis ) {
m_stack.top() = glm::rotate( m_stack.top(), Angle, Axis );
upload(); }
void
translate( glm::vec3 const &Translation ) {
m_stack.top() = glm::translate( m_stack.top(), Translation );
upload(); }
void
multiply( glm::mat4 const &Matrix ) {
m_stack.top() *= Matrix;
upload(); }
void
perspective( float const Fovy, float const Aspect, float const Znear, float const Zfar ) {
m_stack.top() *= glm::perspective( Fovy, Aspect, Znear, Zfar );
upload(); }
void
look_at( glm::vec3 const &Eye, glm::vec3 const &Center, glm::vec3 const &Up ) {
m_stack.top() *= glm::lookAt( Eye, Center, Up );
upload(); }
private:
// types:
typedef std::stack<glm::mat4> mat4_stack;
// methods:
void
upload() { ::glLoadMatrixf( &m_stack.top()[0][0] ); }
// members:
mat4_stack m_stack;
};
enum stack_mode { gl_projection = 0, gl_modelview = 1 };
typedef std::vector<opengl_stack> openglstack_array;
public:
// constructors:
opengl_matrices() {
m_stacks.emplace_back(); // projection
m_stacks.emplace_back(); // modelview
}
// methods:
void
mode( GLuint const Mode ) {
switch( Mode ) {
case GL_PROJECTION: { m_mode = stack_mode::gl_projection; break; }
case GL_MODELVIEW: { m_mode = stack_mode::gl_modelview; break; }
default: { break; } }
glMatrixMode( Mode ); }
glm::mat4 const &
data( GLuint const Mode = -1 ) const {
switch( Mode ) {
case GL_PROJECTION: { return m_stacks[ stack_mode::gl_projection ].data(); }
case GL_MODELVIEW: { return m_stacks[ stack_mode::gl_modelview ].data(); }
default: { return m_stacks[ m_mode ].data(); } } }
float const *
data_array( GLuint const Mode = -1 ) const {
return glm::value_ptr( data( Mode ) ); }
void
push_matrix() { m_stacks[ m_mode ].push_matrix(); }
void
pop_matrix() { m_stacks[ m_mode ].pop_matrix(); }
void
load_identity() { m_stacks[ m_mode ].load_identity(); }
template <typename _Type>
void
rotate( _Type const Angle, _Type const X, _Type const Y, _Type const Z ) {
m_stacks[ m_mode ].rotate(
static_cast<float>(Angle) * 0.0174532925f, // deg2rad
glm::vec3(
static_cast<float>(X),
static_cast<float>(Y),
static_cast<float>(Z) ) ); }
template <typename _Type>
void
translate( _Type const X, _Type const Y, _Type const Z ) {
m_stacks[ m_mode ].translate(
glm::vec3(
static_cast<float>( X ),
static_cast<float>( Y ),
static_cast<float>( Z ) ) ); }
template <typename _Type>
void
multiply( _Type const *Matrix ) {
m_stacks[ m_mode ].multiply(
glm::make_mat4( Matrix ) ); }
template <typename _Type>
void
perspective( _Type const Fovy, _Type const Aspect, _Type const Znear, _Type const Zfar ) {
m_stacks[ m_mode ].perspective(
static_cast<float>(Fovy) * 0.0174532925f, // deg2rad
static_cast<float>( Aspect ),
static_cast<float>( Znear ),
static_cast<float>( Zfar ) ); }
template <typename _Type>
void
look_at( _Type const Eyex, _Type const Eyey, _Type const Eyez, _Type const Centerx, _Type const Centery, _Type const Centerz, _Type const Upx, _Type const Upy, _Type const Upz ) {
m_stacks[ m_mode ].look_at(
glm::vec3(
static_cast<float>( Eyex ),
static_cast<float>( Eyey ),
static_cast<float>( Eyez ) ),
glm::vec3(
static_cast<float>( Centerx ),
static_cast<float>( Centery ),
static_cast<float>( Centerz ) ),
glm::vec3(
static_cast<float>( Upx ),
static_cast<float>( Upy ),
static_cast<float>( Upz ) ) ); }
private:
// members:
stack_mode m_mode{ stack_mode::gl_projection };
openglstack_array m_stacks;
};
extern opengl_matrices OpenGLMatrices;
// NOTE: standard opengl calls re-definitions
#define glMatrixMode OpenGLMatrices.mode
#define glPushMatrix OpenGLMatrices.push_matrix
#define glPopMatrix OpenGLMatrices.pop_matrix
#define glLoadIdentity OpenGLMatrices.load_identity
#define glRotated OpenGLMatrices.rotate
#define glRotatef OpenGLMatrices.rotate
#define glTranslated OpenGLMatrices.translate
#define glTranslatef OpenGLMatrices.translate
// NOTE: no scale override as we aren't using it anywhere
#define glMultMatrixd OpenGLMatrices.multiply
#define glMultMatrixf OpenGLMatrices.multiply
#define gluPerspective OpenGLMatrices.perspective
#define gluLookAt OpenGLMatrices.look_at
//---------------------------------------------------------------------------

View File

@@ -15,6 +15,8 @@ http://mozilla.org/MPL/2.0/.
#include "dynobj.h" #include "dynobj.h"
#include "uilayer.h" #include "uilayer.h"
#include "logs.h" #include "logs.h"
#include "usefull.h"
#include "World.h"
opengl_renderer GfxRenderer; opengl_renderer GfxRenderer;
extern TWorld World; extern TWorld World;
@@ -101,6 +103,12 @@ opengl_renderer::Init( GLFWwindow *Window ) {
World.shader = gl_program_light({ gl_shader("lighting.vert"), gl_shader("blinnphong.frag") }); World.shader = gl_program_light({ gl_shader("lighting.vert"), gl_shader("blinnphong.frag") });
Global::daylight.intensity = 1.0f; //m7todo: przenieść Global::daylight.intensity = 1.0f; //m7todo: przenieść
WriteLog("Loading common gfx data...");
m_glaretextureid = GetTextureId("fx\\lightglare", szTexturePath);
m_suntextureid = GetTextureId("fx\\sun", szTexturePath);
m_moontextureid = GetTextureId("fx\\moon", szTexturePath);
WriteLog("...gfx data pre-loading done");
return true; return true;
} }
@@ -115,29 +123,21 @@ opengl_renderer::Render() {
::glDepthFunc( GL_LEQUAL ); ::glDepthFunc( GL_LEQUAL );
::glMatrixMode( GL_PROJECTION ); // select the Projection Matrix ::glMatrixMode( GL_PROJECTION ); // select the Projection Matrix
glm::mat4 projection = glm::perspective( ::gluPerspective(
Global::FieldOfView / Global::ZoomFactor * 0.0174532925f, Global::FieldOfView / Global::ZoomFactor,
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ), std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
0.1f * Global::ZoomFactor, 0.1f * Global::ZoomFactor,
m_drawrange * Global::fDistanceFactor ); m_drawrange * Global::fDistanceFactor );
::glLoadMatrixf( &projection[0][0] );
::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix ::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
glm::mat4 modelview( 1.0f );
::glLoadIdentity(); ::glLoadIdentity();
if( World.InitPerformed() ) { if( World.InitPerformed() ) {
World.Camera.SetMatrix( modelview ); World.Camera.SetMatrix();
::glLoadMatrixf( &modelview[ 0 ][ 0 ] ); m_camera.update_frustum();
m_camera.update_frustum( projection, modelview );
if( !Global::bWireFrame ) { Render( &World.Environment );
// bez nieba w trybie rysowania linii
World.Environment.render();
}
glDebug("rendering ground");
World.Ground.Render( World.Camera.Pos ); World.Ground.Render( World.Camera.Pos );
glDebug("rendering cab"); glDebug("rendering cab");
@@ -154,12 +154,135 @@ opengl_renderer::Render() {
return true; // for now always succeed return true; // for now always succeed
} }
#ifndef EU07_USE_OLD_RENDERCODE bool
opengl_renderer::Render( world_environment *Environment ) {
if( Global::bWireFrame ) {
// bez nieba w trybie rysowania linii
return false;
}
Bind( 0 );
::glDisable( GL_LIGHTING );
::glDisable( GL_DEPTH_TEST );
::glDepthMask( GL_FALSE );
::glPushMatrix();
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
// setup fog
if( Global::fFogEnd > 0 ) {
// fog setup
::glFogfv( GL_FOG_COLOR, Global::FogColor );
::glFogf( GL_FOG_DENSITY, 1.0f / Global::fFogEnd );
::glEnable( GL_FOG );
}
else { ::glDisable( GL_FOG ); }
Environment->m_skydome.Render();
Environment->m_stars.render();
float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f;
float3 suncolor = interpolate(
float3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ),
float3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ),
duskfactor );
if( DebugModeFlag == true ) {
// mark sun position for easier debugging
Environment->m_sun.render();
Environment->m_moon.render();
}
// render actual sun and moon
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
::glDisable( GL_LIGHTING );
::glDisable( GL_ALPHA_TEST );
::glEnable( GL_BLEND );
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
// sun
{
Bind( m_suntextureid );
::glColor4f( suncolor.x, suncolor.y, suncolor.z, 1.0f );
auto const sunvector = Environment->m_sun.getDirection();
auto const sunposition = modelview * glm::vec4( sunvector.x, sunvector.y, sunvector.z, 1.0f );
::glPushMatrix();
::glLoadIdentity(); // macierz jedynkowa
::glTranslatef( sunposition.x, sunposition.y, sunposition.z ); // początek układu zostaje bez zmian
float const size = 0.045f;
::glBegin( GL_TRIANGLE_STRIP );
::glTexCoord2f( 1.0f, 1.0f ); ::glVertex3f( -size, size, 0.0f );
::glTexCoord2f( 1.0f, 0.0f ); ::glVertex3f( -size, -size, 0.0f );
::glTexCoord2f( 0.0f, 1.0f ); ::glVertex3f( size, size, 0.0f );
::glTexCoord2f( 0.0f, 0.0f ); ::glVertex3f( size, -size, 0.0f );
::glEnd();
::glPopMatrix();
}
// moon
{
Bind( m_moontextureid );
float3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, 1.0f - Global::fLuminance * 0.5f );
auto const moonvector = Environment->m_moon.getDirection();
auto const moonposition = modelview * glm::vec4( moonvector.x, moonvector.y, moonvector.z, 1.0f );
::glPushMatrix();
::glLoadIdentity(); // macierz jedynkowa
::glTranslatef( moonposition.x, moonposition.y, moonposition.z );
float const size = 0.02f; // TODO: expose distance/scale factor from the moon object
// choose the moon appearance variant, based on current moon phase
// NOTE: implementation specific, 8 variants are laid out in 3x3 arrangement
// from new moon onwards, top left to right bottom (last spot is left for future use, if any)
auto const moonphase = Environment->m_moon.getPhase();
float moonu, moonv;
if( moonphase < 1.84566f ) { moonv = 1.0f - 0.0f; moonu = 0.0f; }
else if( moonphase < 5.53699f ) { moonv = 1.0f - 0.0f; moonu = 0.333f; }
else if( moonphase < 9.22831f ) { moonv = 1.0f - 0.0f; moonu = 0.667f; }
else if( moonphase < 12.91963f ) { moonv = 1.0f - 0.333f; moonu = 0.0f; }
else if( moonphase < 16.61096f ) { moonv = 1.0f - 0.333f; moonu = 0.333f; }
else if( moonphase < 20.30228f ) { moonv = 1.0f - 0.333f; moonu = 0.667f; }
else if( moonphase < 23.99361f ) { moonv = 1.0f - 0.667f; moonu = 0.0f; }
else if( moonphase < 27.68493f ) { moonv = 1.0f - 0.667f; moonu = 0.333f; }
else { moonv = 1.0f - 0.0f; moonu = 0.0f; }
::glBegin( GL_TRIANGLE_STRIP );
::glTexCoord2f( moonu, moonv ); ::glVertex3f( -size, size, 0.0f );
::glTexCoord2f( moonu, moonv - 0.333f ); ::glVertex3f( -size, -size, 0.0f );
::glTexCoord2f( moonu + 0.333f, moonv ); ::glVertex3f( size, size, 0.0f );
::glTexCoord2f( moonu + 0.333f, moonv - 0.333f ); ::glVertex3f( size, -size, 0.0f );
::glEnd();
::glPopMatrix();
}
::glPopAttrib();
// clouds
Environment->m_clouds.Render(
interpolate( Environment->m_skydome.GetAverageColor(), suncolor, duskfactor * 0.25f )
* ( 1.0f - Global::Overcast * 0.5f ) // overcast darkens the clouds
* 2.5f ); // arbitrary adjustment factor
Global::daylight.intensity = 1.0f;
::glPopMatrix();
::glDepthMask( GL_TRUE );
::glEnable( GL_DEPTH_TEST );
::glEnable( GL_LIGHTING );
return true;
}
bool bool
opengl_renderer::Render( TGround *Ground ) { opengl_renderer::Render( TGround *Ground ) {
glDisable( GL_BLEND ); glDisable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.35f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f glAlphaFunc( GL_GREATER, 0.45f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
glEnable( GL_LIGHTING ); glEnable( GL_LIGHTING );
glColor3f( 1.0f, 1.0f, 1.0f ); glColor3f( 1.0f, 1.0f, 1.0f );
@@ -194,6 +317,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
Dynamic->renderme = true; Dynamic->renderme = true;
// setup
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
double squaredistance = SquareMagnitude( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor; double squaredistance = SquareMagnitude( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor;
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
@@ -216,36 +340,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
Global::daylight.intensity = Dynamic->fShade; Global::daylight.intensity = Dynamic->fShade;
} }
// TODO: implement universal render path down the road // render
if( Global::bUseVBO ) {
// wersja VBO
if( Dynamic->mdLowPolyInt ) {
if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) {
// enable cab light if needed
if( Dynamic->InteriorLightLevel > 0.0f ) {
// crude way to light the cabin, until we have something more complete in place
auto const cablight = Dynamic->InteriorLight * Dynamic->InteriorLightLevel;
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x );
}
Dynamic->mdLowPolyInt->RaRender( squaredistance, Dynamic->Material()->replacable_skins, Dynamic->Material()->textures_alpha );
if( Dynamic->InteriorLightLevel > 0.0f ) {
// reset the overall ambient
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
}
}
}
Dynamic->mdModel->RaRender( squaredistance, Dynamic->Material()->replacable_skins, Dynamic->Material()->textures_alpha );
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Dynamic->mdLoad->RaRender( squaredistance, Dynamic->Material()->replacable_skins, Dynamic->Material()->textures_alpha );
}
else {
// wersja Display Lists
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
// low poly interior // low poly interior
if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) {
@@ -271,8 +366,8 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
}
// post-render cleanup
if( Dynamic->fShade > 0.0f ) { if( Dynamic->fShade > 0.0f ) {
// restore regular light level // restore regular light level
Global::daylight.intensity = 1.0f; Global::daylight.intensity = 1.0f;
@@ -302,13 +397,24 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
Model->Root->fSquareDist = Squaredistance; // zmienna globalna! Model->Root->fSquareDist = Squaredistance; // zmienna globalna!
// TODO: unify the render code after generic buffers are in place
// setup
if( false == Model->StartVBO() )
return false;
Model->Root->ReplacableSet( Model->Root->ReplacableSet(
( Material != nullptr ? ( Material != nullptr ?
Material->replacable_skins : Material->replacable_skins :
nullptr ), nullptr ),
alpha ); alpha );
Model->Root->RenderDL(); Model->Root->pRoot = Model;
// render
Render(Model->Root);
// post-render cleanup
Model->EndVBO();
return true; return true;
} }
@@ -332,6 +438,154 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
return result; return result;
} }
void opengl_renderer::Render(TSubModel *Submodel)
{
World.shader.set_mv(OpenGLMatrices.data(GL_MODELVIEW));
World.shader.set_p(OpenGLMatrices.data(GL_PROJECTION));
Render(Submodel, OpenGLMatrices.data(GL_MODELVIEW));
}
void opengl_renderer::Render_Alpha(TSubModel *Submodel)
{
World.shader.set_mv(OpenGLMatrices.data(GL_MODELVIEW));
World.shader.set_p(OpenGLMatrices.data(GL_PROJECTION));
Render_Alpha(Submodel, OpenGLMatrices.data(GL_MODELVIEW));
}
void
opengl_renderer::Render( TSubModel *Submodel, glm::mat4 m) {
if( ( Submodel->iVisible )
&& ( TSubModel::fSquareDist >= ( Submodel->fSquareMinDist / Global::fDistanceFactor ) )
&& ( TSubModel::fSquareDist <= ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) ) )
{
glm::mat4 mm = m;
if (Submodel->iFlags & 0xC000)
{
if (Submodel->fMatrix)
mm *= glm::make_mat4(Submodel->fMatrix->e);
if (Submodel->b_Anim)
Submodel->RaAnimation(mm, Submodel->b_Anim);
World.shader.set_mv(mm);
}
if( Submodel->eType < TP_ROTATOR ) {
// renderowanie obiektów OpenGL
if( Submodel->iAlpha & Submodel->iFlags & 0x1F ) // rysuj gdy element nieprzezroczysty
{
// material configuration:
// textures...
if( Submodel->TextureID < 0 )
{ // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
}
else {
// również 0
Bind( Submodel->TextureID );
}
/*
::glColor3fv( Submodel->f4Diffuse ); // McZapkie-240702: zamiast ub
// ...luminance
if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse );
}
*/
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
::glDrawArrays( Submodel->eType, Submodel->iVboPtr, Submodel->iNumVerts );
/*
// post-draw reset
if( Global::fLuminance < Submodel->fLight ) {
// restore default (lack of) brightness
glm::vec4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f );
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( noemission ) );
}
*/
}
}
//m7todo: restore
/*
else if( Submodel->eType == TP_FREESPOTLIGHT ) {
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
auto const lightcenter = modelview * glm::vec4( 0.0f, 0.0f, -0.05f, 1.0f ); // pozycja punktu świecącego względem kamery
Submodel->fCosViewAngle = glm::dot( glm::normalize( modelview * glm::vec4( 0.0f, 0.0f, -1.0f, 1.0f ) - lightcenter ), glm::normalize( -lightcenter ) );
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) // kąt większy niż maksymalny stożek swiatła
{
float lightlevel = 1.0f;
// view angle attenuation
float const anglefactor = ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
// distance attenuation. NOTE: since it's fixed pipeline with built-in gamma correction we're using linear attenuation
// we're capping how much effect the distance attenuation can have, otherwise the lights get too tiny at regular distances
float const distancefactor = std::max( 0.5, ( Submodel->fSquareMaxDist - TSubModel::fSquareDist ) / ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) );
if( lightlevel > 0.0f ) {
// material configuration:
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT );
Bind( 0 );
::glPointSize( std::max( 2.0f, 4.0f * distancefactor * anglefactor ) );
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], lightlevel * anglefactor );
::glDisable( GL_LIGHTING );
::glEnable( GL_BLEND );
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
::glDrawArrays( GL_POINTS, Submodel->iVboPtr, Submodel->iNumVerts );
// post-draw reset
::glPopAttrib();
}
}
}
else if( Submodel->eType == TP_STARS ) {
if( Global::fLuminance < Submodel->fLight ) {
// material configuration:
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT );
Bind( 0 );
::glDisable( GL_LIGHTING );
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
// NOTE: we're doing manual switch to color vbo setup, because there doesn't seem to be any convenient way available atm
// TODO: implement easier way to go about it
::glDisableClientState( GL_NORMAL_ARRAY );
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
::glEnableClientState( GL_COLOR_ARRAY );
::glColorPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // kolory
::glDrawArrays( GL_POINTS, Submodel->iVboPtr, Submodel->iNumVerts );
::glDisableClientState( GL_COLOR_ARRAY );
::glEnableClientState( GL_NORMAL_ARRAY );
::glEnableClientState( GL_TEXTURE_COORD_ARRAY );
// post-draw reset
::glPopAttrib();
}
}
*/
if( Submodel->Child != NULL )
if( Submodel->iAlpha & Submodel->iFlags & 0x001F0000 )
Render( Submodel->Child, mm );
if( Submodel->iFlags & 0xC000 )
World.shader.set_mv(m);
}
if( Submodel->b_Anim < at_SecondsJump )
Submodel->b_Anim = at_None; // wyłączenie animacji dla kolejnego użycia subm
if( Submodel->Next )
if( Submodel->iAlpha & Submodel->iFlags & 0x1F000000 )
Render( Submodel->Next, m ); // dalsze rekurencyjnie
}
bool bool
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) { opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
@@ -340,8 +594,9 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
return false; return false;
} }
// setup
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
double squaredistance = SquareMagnitude( Global::pCameraPosition - Dynamic->vPosition ); double squaredistance = SquareMagnitude( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor;
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
::glPushMatrix(); ::glPushMatrix();
@@ -353,9 +608,13 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii ::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii
::glMultMatrixd( Dynamic->mMatrix.getArray() ); ::glMultMatrixd( Dynamic->mMatrix.getArray() );
// wersja Display Lists
// NOTE: VBO path is removed if( Dynamic->fShade > 0.0f ) {
// TODO: implement universal render path down the road // change light level based on light level of the occupied track
Global::daylight.intensity = Dynamic->fShade;
}
// render
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
// low poly interior // low poly interior
if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) {
@@ -382,6 +641,12 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance ); Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
// post-render cleanup
if( Dynamic->fShade > 0.0f ) {
// restore regular light level
Global::daylight.intensity = 1.0f;
}
::glPopMatrix(); ::glPopMatrix();
if( Dynamic->btnOn ) if( Dynamic->btnOn )
@@ -405,13 +670,24 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
Model->Root->fSquareDist = Squaredistance; // zmienna globalna! Model->Root->fSquareDist = Squaredistance; // zmienna globalna!
// TODO: unify the render code after generic buffers are in place
// setup
if( false == Model->StartVBO() )
return false;
Model->Root->ReplacableSet( Model->Root->ReplacableSet(
( Material != nullptr ? ( Material != nullptr ?
Material->replacable_skins : Material->replacable_skins :
nullptr ), nullptr ),
alpha ); alpha );
Model->Root->RenderAlphaDL(); Model->Root->pRoot = Model;
// render
Render_Alpha( Model->Root );
// post-render cleanup
Model->EndVBO();
return true; return true;
} }
@@ -434,8 +710,129 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
return result; return result;
} }
void
opengl_renderer::Render_Alpha( TSubModel *Submodel, glm::mat4 m) {
// renderowanie przezroczystych przez DL
if( ( Submodel->iVisible )
&& ( TSubModel::fSquareDist >= ( Submodel->fSquareMinDist / Global::fDistanceFactor ) )
&& ( TSubModel::fSquareDist <= ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) ) ) {
glm::mat4 mm = m;
if (Submodel->iFlags & 0xC000)
{
if (Submodel->fMatrix)
mm *= glm::make_mat4(Submodel->fMatrix->e);
if (Submodel->b_Anim)
Submodel->RaAnimation(mm, Submodel->b_Anim);
World.shader.set_mv(mm);
}
if( Submodel->eType < TP_ROTATOR ) {
// renderowanie obiektów OpenGL
if( Submodel->iAlpha & Submodel->iFlags & 0x2F ) // rysuj gdy element przezroczysty
{
// textures...
if( Submodel->TextureID < 0 ) { // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
}
else {
// również 0
Bind( Submodel->TextureID );
}
/*
::glColor3fv( Submodel->f4Diffuse ); // McZapkie-240702: zamiast ub
// ...luminance
if( Global::fLuminance < Submodel->fLight ) {
// zeby swiecilo na kolorowo
::glMaterialfv( GL_FRONT, GL_EMISSION, Submodel->f4Diffuse );
}
*/
// main draw call. TODO: generic buffer base class, specialized for vbo, dl etc
::glDrawArrays( Submodel->eType, Submodel->iVboPtr, Submodel->iNumVerts );
/*
// post-draw reset
if( Global::fLuminance < Submodel->fLight ) {
// restore default (lack of) brightness
glm::vec4 const noemission( 0.0f, 0.0f, 0.0f, 1.0f );
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( noemission ) );
}
*/
}
}
#if 0
else if( Submodel->eType == TP_FREESPOTLIGHT ) {
if( Global::fLuminance < Submodel->fLight ) {
// NOTE: we're forced here to redo view angle calculations etc, because this data isn't instanced but stored along with the single mesh
// TODO: separate instance data from reusable geometry
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
auto const lightcenter = modelview * glm::vec4( 0.0f, 0.0f, -0.05f, 1.0f ); // pozycja punktu świecącego względem kamery
Submodel->fCosViewAngle = glm::dot( glm::normalize( modelview * glm::vec4( 0.0f, 0.0f, -1.0f, 1.0f ) - lightcenter ), glm::normalize( -lightcenter ) );
float glarelevel = 0.6f; // luminosity at night is at level of ~0.1, so the overall resulting transparency is ~0.5 at full 'brightness'
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) {
glarelevel *= ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
glarelevel = std::max( 0.0f, glarelevel - static_cast<float>(Global::fLuminance) );
if( glarelevel > 0.0f ) {
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
Bind( m_glaretextureid );
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], glarelevel );
::glDisable( GL_LIGHTING );
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
::glPushMatrix();
::glLoadIdentity(); // macierz jedynkowa
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
::glRotated( atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt
// TODO: turn the drawing instructions into a compiled call / array
::glBegin( GL_TRIANGLE_STRIP );
float const size = 2.5f;
::glTexCoord2f( 1.0f, 1.0f ); ::glVertex3f( -size, size, 0.0f );
::glTexCoord2f( 0.0f, 1.0f ); ::glVertex3f( size, size, 0.0f );
::glTexCoord2f( 1.0f, 0.0f ); ::glVertex3f( -size, -size, 0.0f );
::glTexCoord2f( 0.0f, 0.0f ); ::glVertex3f( size, -size, 0.0f );
/*
// NOTE: we could do simply...
vec3 vertexPosition_worldspace =
particleCenter_wordspace
+ CameraRight_worldspace * squareVertices.x * BillboardSize.x
+ CameraUp_worldspace * squareVertices.y * BillboardSize.y;
// ...etc instead IF we had easy access to camera's forward and right vectors. TODO: check if Camera matrix is accessible
*/
::glEnd();
::glPopMatrix();
::glPopAttrib();
}
}
}
}
#endif #endif
if( Submodel->Child != NULL )
if( Submodel->iAlpha & Submodel->iFlags & 0x002F0000 )
Render_Alpha( Submodel->Child, mm );
if( Submodel->iFlags & 0xC000 )
World.shader.set_mv(m);
}
if( Submodel->b_aAnim < at_SecondsJump )
Submodel->b_aAnim = at_None; // wyłączenie animacji dla kolejnego użycia submodelu
if( Submodel->Next != NULL )
if( Submodel->iAlpha & Submodel->iFlags & 0x2F000000 )
Render_Alpha( Submodel->Next, m );
};
void void
opengl_renderer::Update ( double const Deltatime ) { opengl_renderer::Update ( double const Deltatime ) {
@@ -530,9 +927,9 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
// if the light passed tests so far, it's good enough // if the light passed tests so far, it's good enough
auto const luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels auto const luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels
float3 position(scenelight.position.x, scenelight.position.y, scenelight.position.z); glm::vec3 position(scenelight.position.x, scenelight.position.y, scenelight.position.z);
float3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z); glm::vec3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z);
float3 color(scenelight.color.x, glm::vec3 color(scenelight.color.x,
scenelight.color.y, scenelight.color.y,
scenelight.color.z); scenelight.color.z);
@@ -541,6 +938,9 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
++renderlight; ++renderlight;
} }
World.shader.set_ambient(Global::daylight.ambient);
World.shader.set_light(0, gl_program_light::DIR, glm::vec3(0.0f), Global::daylight.direction,
0.0f, 0.0f, Global::daylight.color, 0.0f, 0.0f);
World.shader.set_light_count((GLuint)renderlight + 1); World.shader.set_light_count((GLuint)renderlight + 1);
} }
@@ -560,8 +960,8 @@ opengl_renderer::Init_caps() {
+ " Vendor: " + std::string( (char *)glGetString( GL_VENDOR ) ) + " Vendor: " + std::string( (char *)glGetString( GL_VENDOR ) )
+ " OpenGL Version: " + oglversion ); + " OpenGL Version: " + oglversion );
if( !GLEW_VERSION_1_4 ) { if( !GLEW_VERSION_3_2 ) {
ErrorLog( "Requires openGL >= 1.4" ); ErrorLog( "Requires openGL >= 3.2" );
return false; return false;
} }

View File

@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
#include "frustum.h" #include "frustum.h"
#include "ground.h" #include "ground.h"
#include "shader.h" #include "shader.h"
#include "World.h"
// encapsulates basic rendering setup. // encapsulates basic rendering setup.
// for modern opengl this translates to a specific collection of glsl shaders, // for modern opengl this translates to a specific collection of glsl shaders,
@@ -37,6 +38,9 @@ class opengl_camera {
public: public:
// methods: // methods:
inline inline
void
update_frustum() { m_frustum.calculate(); }
inline
void void
update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); } update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); }
bool bool
@@ -61,7 +65,8 @@ public:
// main draw call. returns false on error // main draw call. returns false on error
bool bool
Render(); Render();
#ifndef EU07_USE_OLD_RENDERCODE bool
Render( world_environment *Environment );
bool bool
Render( TGround *Ground ); Render( TGround *Ground );
bool bool
@@ -70,13 +75,18 @@ public:
Render( TModel3d *Model, material_data const *Material, double const Squaredistance ); Render( TModel3d *Model, material_data const *Material, double const Squaredistance );
bool bool
Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ); Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
void
Render( TSubModel *Submodel, glm::mat4 m );
void Render(TSubModel *Submodel);
void Render_Alpha(TSubModel *Submodel);
bool bool
Render_Alpha( TDynamicObject *Dynamic ); Render_Alpha( TDynamicObject *Dynamic );
bool bool
Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance ); Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance );
bool bool
Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ); Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
#endif void
Render_Alpha( TSubModel *Submodel, glm::mat4 m);
// maintenance jobs // maintenance jobs
void void
Update( double const Deltatime); Update( double const Deltatime);
@@ -119,7 +129,8 @@ private:
}; };
// methods // methods
bool Init_caps(); bool
Init_caps();
// members // members
rendermode renderpass{ rendermode::color }; rendermode renderpass{ rendermode::color };
@@ -130,6 +141,9 @@ private:
double m_updateaccumulator{ 0.0 }; double m_updateaccumulator{ 0.0 };
std::string m_debuginfo; std::string m_debuginfo;
GLFWwindow *m_window{ nullptr }; GLFWwindow *m_window{ nullptr };
texture_manager::size_type m_glaretextureid{ -1 };
texture_manager::size_type m_suntextureid{ -1 };
texture_manager::size_type m_moontextureid{ -1 };
}; };
extern opengl_renderer GfxRenderer; extern opengl_renderer GfxRenderer;

View File

@@ -103,12 +103,12 @@ void gl_program_mvp::copy_gl_mvp()
glUniformMatrix4fv(p_uniform, 1, GL_FALSE, p.e); glUniformMatrix4fv(p_uniform, 1, GL_FALSE, p.e);
} }
void gl_program_mvp::set_mv(glm::mat4 &m) void gl_program_mvp::set_mv(const glm::mat4 &m)
{ {
glUniformMatrix4fv(mv_uniform, 1, GL_FALSE, glm::value_ptr(m)); glUniformMatrix4fv(mv_uniform, 1, GL_FALSE, glm::value_ptr(m));
} }
void gl_program_mvp::set_p(glm::mat4 &m) void gl_program_mvp::set_p(const glm::mat4 &m)
{ {
glUniformMatrix4fv(p_uniform, 1, GL_FALSE, glm::value_ptr(m)); glUniformMatrix4fv(p_uniform, 1, GL_FALSE, glm::value_ptr(m));
} }
@@ -117,7 +117,6 @@ gl_program_light::gl_program_light(std::vector<gl_shader> v) : gl_program_mvp(v)
{ {
ambient_uniform = glGetUniformLocation(id, "ambient"); ambient_uniform = glGetUniformLocation(id, "ambient");
lcount_uniform = glGetUniformLocation(id, "lights_count"); lcount_uniform = glGetUniformLocation(id, "lights_count");
specular_uniform = glGetUniformLocation(id, "specular");
for (size_t i = 0; i < MAX_LIGHTS; i++) for (size_t i = 0; i < MAX_LIGHTS; i++)
{ {
@@ -136,10 +135,10 @@ gl_program_light::gl_program_light(std::vector<gl_shader> v) : gl_program_mvp(v)
glUniform1i(lcount_uniform, 0); glUniform1i(lcount_uniform, 0);
} }
void gl_program_light::set_ambient(float3 &ambient) void gl_program_light::set_ambient(glm::vec3 &ambient)
{ {
glUseProgram(id); glUseProgram(id);
glUniform3fv(ambient_uniform, 1, &ambient.x); glUniform3fv(ambient_uniform, 1, glm::value_ptr(ambient));
} }
void gl_program_light::set_light_count(GLuint count) void gl_program_light::set_light_count(GLuint count)
@@ -148,13 +147,11 @@ void gl_program_light::set_light_count(GLuint count)
glUniform1ui(lcount_uniform, count); glUniform1ui(lcount_uniform, count);
} }
void gl_program_light::set_light(GLuint i, type t, float3 &pos, float3 &dir, void gl_program_light::set_light(GLuint i, type t, glm::vec3 &pos, glm::vec3 &dir,
float in_cutoff, float out_cutoff, float in_cutoff, float out_cutoff,
float3 &color, float linear, float quadratic) glm::vec3 &color, float linear, float quadratic)
{ {
float arr[16]; glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
glGetFloatv(GL_MODELVIEW_MATRIX, arr);
glm::mat4 mv = glm::make_mat4(arr);
glm::vec3 trans_pos = mv * glm::vec4(pos.x, pos.y, pos.z, 1.0f); glm::vec3 trans_pos = mv * glm::vec4(pos.x, pos.y, pos.z, 1.0f);
glm::vec3 trans_dir = mv * glm::vec4(dir.x, dir.y, dir.z, 0.0f); glm::vec3 trans_dir = mv * glm::vec4(dir.x, dir.y, dir.z, 0.0f);
@@ -165,13 +162,7 @@ void gl_program_light::set_light(GLuint i, type t, float3 &pos, float3 &dir,
glUniform3fv(lights_uniform[i].dir, 1, glm::value_ptr(trans_dir)); glUniform3fv(lights_uniform[i].dir, 1, glm::value_ptr(trans_dir));
glUniform1f(lights_uniform[i].in_cutoff, in_cutoff); glUniform1f(lights_uniform[i].in_cutoff, in_cutoff);
glUniform1f(lights_uniform[i].out_cutoff, out_cutoff); glUniform1f(lights_uniform[i].out_cutoff, out_cutoff);
glUniform3fv(lights_uniform[i].color, 1, &color.x); glUniform3fv(lights_uniform[i].color, 1, glm::value_ptr(color));
glUniform1f(lights_uniform[i].linear, linear); glUniform1f(lights_uniform[i].linear, linear);
glUniform1f(lights_uniform[i].quadratic, quadratic); glUniform1f(lights_uniform[i].quadratic, quadratic);
} }
void gl_program_light::set_object(float specular)
{
glUseProgram(id);
glUniform1f(specular_uniform, specular);
}

View File

@@ -35,8 +35,8 @@ public:
gl_program_mvp() = default; gl_program_mvp() = default;
gl_program_mvp(std::vector<gl_shader>); gl_program_mvp(std::vector<gl_shader>);
void set_mv(glm::mat4 &); void set_mv(const glm::mat4 &);
void set_p(glm::mat4 &); void set_p(const glm::mat4 &);
void copy_gl_mvp(); void copy_gl_mvp();
}; };
@@ -55,16 +55,14 @@ public:
gl_program_light() = default; gl_program_light() = default;
gl_program_light(std::vector<gl_shader>); gl_program_light(std::vector<gl_shader>);
void set_ambient(float3 &ambient); void set_ambient(glm::vec3 &ambient);
void set_light_count(GLuint count); void set_light_count(GLuint count);
void set_light(GLuint id, type t, float3 &pos, float3 &dir, float in_cutoff, float out_cutoff, void set_light(GLuint id, type t, glm::vec3 &pos, glm::vec3 &dir, float in_cutoff, float out_cutoff,
float3 &color, float linear, float quadratic); glm::vec3 &color, float linear, float quadratic);
void set_object(float specular);
private: private:
GLuint lcount_uniform; GLuint lcount_uniform;
GLuint ambient_uniform; GLuint ambient_uniform;
GLuint specular_uniform;
struct light_s struct light_s
{ {
GLuint type; GLuint type;

View File

@@ -39,21 +39,21 @@ void TSky::Render( float3 const &Tint )
GfxRenderer.Disable_Lights(); GfxRenderer.Disable_Lights();
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x ); ::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x );
#endif #endif
if (Global::bUseVBO) #ifdef EU07_USE_OLD_RENDERCODE
if( Global::bUseVBO )
{ // renderowanie z VBO { // renderowanie z VBO
mdCloud->RaRender( 100, 0 ); mdCloud->RaRender( 100, 0 );
mdCloud->RaRenderAlpha(100, 0); mdCloud->RaRenderAlpha(100, 0);
} }
else else
{ // renderowanie z Display List { // renderowanie z Display List
#ifdef EU07_USE_OLD_RENDERCODE
mdCloud->Render(100, 0); mdCloud->Render(100, 0);
mdCloud->RenderAlpha(100, 0); mdCloud->RenderAlpha(100, 0);
}
#else #else
GfxRenderer.Render( mdCloud, nullptr, 100.0 ); GfxRenderer.Render( mdCloud, nullptr, 100.0 );
GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 ); GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 );
#endif #endif
}
#ifdef EU07_USE_OLD_LIGHTING_MODEL #ifdef EU07_USE_OLD_LIGHTING_MODEL
glPopMatrix(); glPopMatrix();
// TODO: re-implement this // TODO: re-implement this

View File

@@ -206,7 +206,7 @@ void CSkyDome::SetGammaCorrection( float const Gamma ) {
void CSkyDome::SetOvercastFactor( float const Overcast ) { void CSkyDome::SetOvercastFactor( float const Overcast ) {
m_overcast = clamp( Overcast, 0.0f, 1.0f ); m_overcast = clamp( Overcast, 0.0f, 1.0f ) * 0.75f; // going above 0.65 makes the model go pretty bad, appearance-wise
} }
void CSkyDome::GetPerez( float *Perez, float Distribution[ 5 ][ 2 ], const float Turbidity ) { void CSkyDome::GetPerez( float *Perez, float Distribution[ 5 ][ 2 ], const float Turbidity ) {
@@ -299,7 +299,7 @@ void CSkyDome::RebuildColors() {
// luminance(Y) for clear & overcast sky // luminance(Y) for clear & overcast sky
float const yclear = PerezFunctionO2( perezluminance, icostheta, gamma, cosgamma2, zenithluminance ); float const yclear = PerezFunctionO2( perezluminance, icostheta, gamma, cosgamma2, zenithluminance );
float const yover = ( 1.0f + 2.0f * vertex.y ) / 3.0f; float const yover = zenithluminance * ( 1.0f + 2.0f * vertex.y ) / 3.0f;
float const Y = interpolate( yclear, yover, m_overcast ); float const Y = interpolate( yclear, yover, m_overcast );
float const X = (x / y) * Y; float const X = (x / y) * Y;
@@ -317,6 +317,11 @@ void CSkyDome::RebuildColors() {
colorconverter.z = 1.0f - exp( -m_expfactor * colorconverter.z ); colorconverter.z = 1.0f - exp( -m_expfactor * colorconverter.z );
} }
// desaturate sky colour, based on overcast level
if( colorconverter.y > 0.0f ) {
colorconverter.y *= ( 1.0f - m_overcast );
}
// override the hue, based on sun height above the horizon. crude way to deal with model shortcomings // override the hue, based on sun height above the horizon. crude way to deal with model shortcomings
// correction begins when the sun is higher than 10 degrees above the horizon, and fully in effect at 10+15 degrees // correction begins when the sun is higher than 10 degrees above the horizon, and fully in effect at 10+15 degrees
float const degreesabovehorizon = 90.0f - m_thetasun * ( 180.0f / M_PI ); float const degreesabovehorizon = 90.0f - m_thetasun * ( 180.0f / M_PI );
@@ -340,8 +345,8 @@ void CSkyDome::RebuildColors() {
*/ */
// crude correction for the times where the model breaks (late night) // crude correction for the times where the model breaks (late night)
// TODO: use proper night sky calculation for these times instead // TODO: use proper night sky calculation for these times instead
if( ( color.x <= 0.0f ) if( ( color.x <= 0.05f )
&& ( color.y <= 0.0f ) ) { && ( color.y <= 0.05f ) ) {
// darken the sky as the sun goes deeper below the horizon // darken the sky as the sun goes deeper below the horizon
// 15:50:75 is picture-based night sky colour. it may not be accurate but looks 'right enough' // 15:50:75 is picture-based night sky colour. it may not be accurate but looks 'right enough'
color.z = 0.75f * std::max( color.z + m_sundirection.y, 0.075f ); color.z = 0.75f * std::max( color.z + m_sundirection.y, 0.075f );

View File

@@ -18,11 +18,16 @@ cStars::render() {
::glPushMatrix(); ::glPushMatrix();
::glRotatef( m_latitude, 1.0f, 0.0f, 0.0f ); // ustawienie osi OY na północ ::glRotatef( m_latitude, 1.0f, 0.0f, 0.0f ); // ustawienie osi OY na północ
::glRotatef( -std::fmod( Global::fTimeAngleDeg, 360.0f ), 0.0f, 1.0f, 0.0f ); // obrót dobowy osi OX ::glRotatef( -std::fmod( (float)Global::fTimeAngleDeg, 360.0f ), 0.0f, 1.0f, 0.0f ); // obrót dobowy osi OX
::glPointSize( 2.0f ); ::glPointSize( 2.0f );
#ifdef EU07_USE_OLD_RENDERCODE #ifdef EU07_USE_OLD_RENDERCODE
if( Global::bUseVBO ) {
m_stars.RaRender( 1.0, 0 );
}
else {
m_stars.Render( 1.0 ); m_stars.Render( 1.0 );
}
#else #else
GfxRenderer.Render( &m_stars, nullptr, 1.0 ); GfxRenderer.Render( &m_stars, nullptr, 1.0 );
#endif #endif

View File

@@ -78,6 +78,7 @@
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "openglmatrixstack.h"
#define STRINGIZE_DETAIL(x) #x #define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x) #define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define glDebug(x) if (GLEW_GREMEDY_string_marker) glStringMarkerGREMEDY(0, __FILE__ ":" STRINGIZE(__LINE__) ": " x); #define glDebug(x) if (GLEW_GREMEDY_string_marker) glStringMarkerGREMEDY(0, __FILE__ ":" STRINGIZE(__LINE__) ": " x);

162
sun.cpp
View File

@@ -4,6 +4,7 @@
#include "globals.h" #include "globals.h"
#include "mtable.h" #include "mtable.h"
#include "usefull.h" #include "usefull.h"
#include "world.h"
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun, // cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
@@ -32,7 +33,7 @@ void
cSun::update() { cSun::update() {
move(); move();
Math3D::vector3 position( 0.0f, 0.0f, -2000.0f ); Math3D::vector3 position( 0.0f, 0.0f, -2000.0f * Global::fDistanceFactor );
position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) ); position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) );
position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) ); position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) );
@@ -48,8 +49,6 @@ cSun::render() {
GLfloat LightPosition[]= { 10.0f, 50.0f, -5.0f, 1.0f }; // ambient GLfloat LightPosition[]= { 10.0f, 50.0f, -5.0f, 1.0f }; // ambient
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition ); glLightfv(GL_LIGHT1, GL_POSITION, LightPosition );
*/ */
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glColor4f( 255.0f/255.0f, 242.0f/255.0f, 231.0f/255.0f, 1.f ); glColor4f( 255.0f/255.0f, 242.0f/255.0f, 231.0f/255.0f, 1.f );
// debug line to locate the sun easier // debug line to locate the sun easier
Math3D::vector3 position = m_position; Math3D::vector3 position = m_position;
@@ -62,8 +61,6 @@ cSun::render() {
// radius is a result of scaling true distance down to 2km -- it's scaled by equal ratio // radius is a result of scaling true distance down to 2km -- it's scaled by equal ratio
gluSphere( sunsphere, (float)(m_body.distance * 9.359157), 12, 12 ); gluSphere( sunsphere, (float)(m_body.distance * 9.359157), 12, 12 );
glPopMatrix(); glPopMatrix();
glEnable(GL_FOG);
glEnable(GL_LIGHTING);
} }
Math3D::vector3 Math3D::vector3
@@ -99,8 +96,8 @@ void cSun::setLocation( float const Longitude, float const Latitude ) {
void cSun::setTime( int const Hour, int const Minute, int const Second ) { void cSun::setTime( int const Hour, int const Minute, int const Second ) {
m_observer.hour = clamp( Hour, -1, 23 ); m_observer.hour = clamp( Hour, -1, 23 );
m_observer.minute = clamp( Minute, 0, 59 ); m_observer.minute = clamp( Minute, -1, 59 );
m_observer.second = clamp( Second, 0, 59 ); m_observer.second = clamp( Second, -1, 59 );
} }
void cSun::setTemperature( float const Temperature ) { void cSun::setTemperature( float const Temperature ) {
@@ -115,11 +112,10 @@ void cSun::setPressure( float const Pressure ) {
void cSun::move() { void cSun::move() {
static double degrad = 57.295779513; // converts from radians to degrees static double radtodeg = 57.295779513; // converts from radians to degrees
static double raddeg = 0.0174532925; // converts from degrees to radians static double degtorad = 0.0174532925; // converts from degrees to radians
SYSTEMTIME localtime; // time for the calculation SYSTEMTIME localtime = Simulation::Time.data(); // time for the calculation
time( &localtime );
if( m_observer.hour >= 0 ) { localtime.wHour = m_observer.hour; } if( m_observer.hour >= 0 ) { localtime.wHour = m_observer.hour; }
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; } if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
@@ -128,49 +124,62 @@ void cSun::move() {
double ut = localtime.wHour double ut = localtime.wHour
+ localtime.wMinute / 60.0 // too low resolution, noticeable skips + localtime.wMinute / 60.0 // too low resolution, noticeable skips
+ localtime.wSecond / 3600.0; // good enough in normal circumstances + localtime.wSecond / 3600.0; // good enough in normal circumstances
/* /*
+ localtime.wMilliseconds / 3600000.0; // for really smooth movement + localtime.wMilliseconds / 3600000.0; // for really smooth movement
*/ */
double daynumber = 367 * localtime.wYear double daynumber = 367 * localtime.wYear
- 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) /12 ) / 4 - 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4
+ 275 * localtime.wMonth / 9 + 275 * localtime.wMonth / 9
+ localtime.wDay + localtime.wDay
- 730530 - 730530
+ (ut / 24.0); + ( ut / 24.0 );
// Universal Coordinated (Greenwich standard) time // Universal Coordinated (Greenwich standard) time
m_observer.utime = ut * 3600.0; m_observer.utime = ut * 3600.0;
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone; m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
// perihelion longitude
// mean longitude m_body.phlong = 282.9404 + 4.70935e-5 * daynumber; // w
m_body.mnlong = 280.460 + 0.9856474 * daynumber; // orbit eccentricity
m_body.mnlong -= 360.0 * (int) ( m_body.mnlong / 360.0 ); // clamp the range to 0-360 double const e = 0.016709 - 1.151e-9 * daynumber;
if( m_body.mnlong < 0.0 ) m_body.mnlong += 360.0;
// mean anomaly // mean anomaly
m_body.mnanom = 357.528 + 0.9856003 * daynumber; m_body.mnanom = clamp_circular( 356.0470 + 0.9856002585 * daynumber ); // M
m_body.mnanom -= 360.0 * (int) ( m_body.mnanom / 360.0 ); // clamp the range to 0-360
if( m_body.mnanom < 0.0 ) m_body.mnanom += 360.0;
// ecliptic longitude
m_body.eclong = m_body.mnlong
+ 1.915 * sin( m_body.mnanom * raddeg )
+ 0.020 * sin ( 2.0 * m_body.mnanom * raddeg );
m_body.eclong -= 360.0 * (int)( m_body.eclong / 360.0 );
if( m_body.eclong < 0.0 ) m_body.eclong += 360.0; // clamp the range to 0-360
// obliquity of the ecliptic // obliquity of the ecliptic
m_body.ecobli = 23.439 - 4.0e-07 * daynumber; m_body.oblecl = 23.4393 - 3.563e-7 * daynumber;
// mean longitude
m_body.mnlong = clamp_circular( m_body.phlong + m_body.mnanom ); // L = w + M
// eccentric anomaly
double const E = m_body.mnanom + radtodeg * e * std::sin( degtorad * m_body.mnanom ) * ( 1.0 + e * std::cos( degtorad * m_body.mnanom ) );
// ecliptic plane rectangular coordinates
double const xv = std::cos( degtorad * E ) - e;
double const yv = std::sin( degtorad * E ) * std::sqrt( 1.0 - e*e );
// distance
m_body.distance = std::sqrt( xv*xv + yv*yv ); // r
// true anomaly
m_body.tranom = radtodeg * std::atan2( yv, xv ); // v
// ecliptic longitude
m_body.eclong = clamp_circular( m_body.tranom + m_body.phlong ); // lon = v + w
/*
// ecliptic rectangular coordinates
double const x = m_body.distance * std::cos( degtorad * m_body.eclong );
double const y = m_body.distance * std::sin( degtorad * m_body.eclong );
double const z = 0.0;
// equatorial rectangular coordinates
double const xequat = x;
double const yequat = y * std::cos( degtorad * m_body.oblecl ) - 0.0 * std::sin( degtorad * m_body.oblecl );
double const zequat = y * std::sin( degtorad * m_body.oblecl ) + 0.0 * std::cos( degtorad * m_body.oblecl );
// declination // declination
m_body.declin = degrad * asin( sin (m_body.ecobli * raddeg) * sin (m_body.eclong * raddeg) ); m_body.declin = radtodeg * std::atan2( zequat, std::sqrt( xequat*xequat + yequat*yequat ) );
// right ascension
m_body.rascen = radtodeg * std::atan2( yequat, xequat );
*/
// declination
m_body.declin = radtodeg * std::asin( std::sin( m_body.oblecl * degtorad ) * std::sin( m_body.eclong * degtorad ) );
// right ascension // right ascension
double top = cos ( raddeg * m_body.ecobli ) * sin ( raddeg * m_body.eclong ); double top = std::cos( degtorad * m_body.oblecl ) * std::sin( degtorad * m_body.eclong );
double bottom = cos ( raddeg * m_body.eclong ); double bottom = std::cos( degtorad * m_body.eclong );
m_body.rascen = degrad * atan2( top, bottom ); m_body.rascen = clamp_circular( radtodeg * std::atan2( top, bottom ) );
if( m_body.rascen < 0.0 ) m_body.rascen += 360.0; // (make it a positive angle)
// Greenwich mean sidereal time // Greenwich mean sidereal time
m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime; m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime;
@@ -192,29 +201,20 @@ void cSun::move() {
double cz; // cosine of the solar zenith angle double cz; // cosine of the solar zenith angle
double tdatcd = cos( raddeg * m_body.declin ); double tdatcd = std::cos( degtorad * m_body.declin );
double tdatch = cos( raddeg * m_body.hrang ); double tdatch = std::cos( degtorad * m_body.hrang );
double tdatcl = cos( raddeg * m_observer.latitude ); double tdatcl = std::cos( degtorad * m_observer.latitude );
double tdatsd = sin( raddeg * m_body.declin ); double tdatsd = std::sin( degtorad * m_body.declin );
double tdatsl = sin( raddeg * m_observer.latitude ); double tdatsl = std::sin( degtorad * m_observer.latitude );
cz = tdatsd * tdatsl + tdatcd * tdatcl * tdatch; cz = tdatsd * tdatsl + tdatcd * tdatcl * tdatch;
// (watch out for the roundoff errors) // (watch out for the roundoff errors)
if( fabs (cz) > 1.0 ) { cz >= 0.0 ? cz = 1.0 : cz = -1.0; } if( fabs( cz ) > 1.0 ) { cz >= 0.0 ? cz = 1.0 : cz = -1.0; }
m_body.zenetr = acos( cz ) * degrad; m_body.zenetr = std::acos( cz ) * radtodeg;
m_body.elevetr = 90.0 - m_body.zenetr; m_body.elevetr = 90.0 - m_body.zenetr;
refract(); refract();
// additional calculations for proper object sizing.
// orbit eccentricity
double e = 0.016709 - 1.151e-9 * daynumber;
// eccentric anomaly
double E = m_body.mnanom + e * degrad * sin(m_body.mnanom) * ( 1.0 + e * cos(m_body.mnanom) );
double xv = cos(E) - e;
double yv = sqrt(1.0 - e*e) * sin(E);
m_body.distance = sqrt( xv*xv + yv*yv );
} }
void cSun::refract() { void cSun::refract() {
@@ -258,10 +258,9 @@ void cSun::irradiance() {
static double degrad = 57.295779513; // converts from radians to degrees static double degrad = 57.295779513; // converts from radians to degrees
static double raddeg = 0.0174532925; // converts from degrees to radians static double raddeg = 0.0174532925; // converts from degrees to radians
SYSTEMTIME localtime; // time for the calculation auto const &localtime = Simulation::Time.data(); // time for the calculation
time( &localtime );
m_body.dayang = ( yearday( localtime.wDay, localtime.wMonth, localtime.wYear ) - 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 = sin( raddeg * m_body.dayang ); // sine of the day angle
double cd = cos( raddeg * m_body.dayang ); // cosine of the day angle or delination double cd = cos( raddeg * 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;
@@ -282,50 +281,3 @@ void cSun::irradiance() {
m_body.etr = 0.0; m_body.etr = 0.0;
} }
} }
int cSun::yearday( int Day, const int Month, const int Year ) {
char daytab[ 2 ][ 13 ] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
int i, leap;
leap = ( Year%4 == 0 ) && ( Year%100 != 0 ) || ( Year%400 == 0 );
for( i = 1; i < Month; ++i )
Day += daytab[ leap ][ i ];
return Day;
}
void cSun::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) {
WORD daytab[ 2 ][ 13 ] = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
WORD idx = 1;
while( (idx < 13) && ( Yearday <= daytab[ leap ][ idx ] )) {
++idx;
}
Month = idx + 1;
Day = Yearday - daytab[ leap ][ idx ];
}
// obtains current time for calculations
void
cSun::time( SYSTEMTIME *Time ) {
::GetLocalTime( Time );
// NOTE: we're currently using local time to determine day/month/year
if( Global::fMoveLight > 0.0 ) {
// TODO: enter scenario-defined day/month/year instead.
daymonth( Time->wDay, Time->wMonth, Time->wYear, static_cast<WORD>(Global::fMoveLight) );
}
Time->wHour = GlobalTime->hh;
Time->wMinute = GlobalTime->mm;
Time->wSecond = std::floor( GlobalTime->mr );
}

10
sun.h
View File

@@ -54,12 +54,6 @@ protected:
void refract(); void refract();
// calculates light intensity at current moment // calculates light intensity at current moment
void irradiance(); void irradiance();
// calculates day of year from given date
int yearday( int Day, int const Month, int const Year );
// calculates day and month from given day of year
void daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
// obtains current time for calculations
void time( SYSTEMTIME *Time );
// members: // members:
GLUquadricObj *sunsphere; // temporary handler for sun positioning test GLUquadricObj *sunsphere; // temporary handler for sun positioning test
@@ -67,10 +61,12 @@ protected:
struct celestialbody { // main planet parameters struct celestialbody { // main planet parameters
double dayang; // day angle (daynum*360/year-length) degrees double dayang; // day angle (daynum*360/year-length) degrees
double phlong; // longitude of perihelion
double mnlong; // mean longitude, degrees double mnlong; // mean longitude, degrees
double mnanom; // mean anomaly, degrees double mnanom; // mean anomaly, degrees
double tranom; // true anomaly, degrees
double eclong; // ecliptic longitude, degrees. double eclong; // ecliptic longitude, degrees.
double ecobli; // obliquity of ecliptic. double oblecl; // obliquity of ecliptic.
double declin; // declination--zenith angle of solar noon at equator, degrees NORTH. double declin; // declination--zenith angle of solar noon at equator, degrees NORTH.
double rascen; // right ascension, degrees double rascen; // right ascension, degrees
double hrang; // hour angle--hour of sun from solar noon, degrees WEST double hrang; // hour angle--hour of sun from solar noon, degrees WEST

View File

@@ -35,7 +35,8 @@ http://mozilla.org/MPL/2.0/.
#define MAKE_ID4(a,b,c,d) (((std::uint32_t)(d)<<24)|((std::uint32_t)(c)<<16)|((std::uint32_t)(b)<<8)|(std::uint32_t)(a)) #define MAKE_ID4(a,b,c,d) (((std::uint32_t)(d)<<24)|((std::uint32_t)(c)<<16)|((std::uint32_t)(b)<<8)|(std::uint32_t)(a))
template <typename _Type> template <typename _Type>
_Type clamp( _Type const Value, _Type const Min, _Type const Max ) { _Type
clamp( _Type const Value, _Type const Min, _Type const Max ) {
_Type value = Value; _Type value = Value;
if( value < Min ) { value = Min; } if( value < Min ) { value = Min; }
@@ -43,8 +44,20 @@ _Type clamp( _Type const Value, _Type const Min, _Type const Max ) {
return value; return value;
} }
// keeps the provided value in specified range 0-Range, as if the range was circular buffer
template <typename _Type> template <typename _Type>
_Type interpolate( _Type const First, _Type const Second, float const Factor ) { _Type
clamp_circular( _Type Value, _Type const Range = static_cast<_Type>(360) ) {
Value -= Range * (int)( Value / Range ); // clamp the range to 0-360
if( Value < 0.0 ) Value += Range;
return Value;
}
template <typename _Type>
_Type
interpolate( _Type const First, _Type const Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor ); return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
} }