mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 20:59:19 +02:00
merge (with bugs)
This commit is contained in:
@@ -686,27 +686,19 @@ int TAnimModel::Flags()
|
||||
//-----------------------------------------------------------------------------
|
||||
// 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
void TAnimModel::RenderDL(vector3 *vPosition)
|
||||
{
|
||||
RaAnimate(); // jednorazowe przeliczenie animacji
|
||||
RaPrepare();
|
||||
if( pModel ) // renderowanie rekurencyjne submodeli
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
pModel->Render(vPosition, &vAngle, ReplacableSkinId, iTexAlpha);
|
||||
#else
|
||||
GfxRenderer.Render( pModel, Material(), *vPosition, vAngle );
|
||||
#endif
|
||||
};
|
||||
void TAnimModel::RenderAlphaDL(vector3 *vPosition)
|
||||
{
|
||||
RaPrepare();
|
||||
if (pModel) // renderowanie rekurencyjne submodeli
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
pModel->RenderAlpha(vPosition, &vAngle, ReplacableSkinId, iTexAlpha);
|
||||
#else
|
||||
GfxRenderer.Render_Alpha( pModel, Material(), *vPosition, vAngle );
|
||||
#endif
|
||||
};
|
||||
|
||||
void TAnimModel::RenderVBO(vector3 *vPosition)
|
||||
@@ -714,15 +706,27 @@ void TAnimModel::RenderVBO(vector3 *vPosition)
|
||||
RaAnimate(); // jednorazowe przeliczenie animacji
|
||||
RaPrepare();
|
||||
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)
|
||||
{
|
||||
RaPrepare();
|
||||
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()
|
||||
|
||||
@@ -175,10 +175,16 @@ class TAnimModel
|
||||
void RenderAlphaDL(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 RenderDL(vector3 *vPosition);
|
||||
*/
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
void RenderDL( vector3 *vPosition );
|
||||
void RenderAlphaDL(vector3 *vPosition);
|
||||
void RenderVBO(vector3 *vPosition);
|
||||
void RenderAlphaVBO(vector3 *vPosition);
|
||||
#else
|
||||
void Render( vector3 *vPosition );
|
||||
void RenderAlpha( vector3 *vPosition );
|
||||
#endif
|
||||
int Flags();
|
||||
void RaAnglesSet(double a, double b, double c)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,8 @@ set(SOURCES
|
||||
"shader.cpp"
|
||||
"frustum.cpp"
|
||||
"uilayer.cpp"
|
||||
"openglmatrixstack.cpp"
|
||||
"moon.cpp"
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
|
||||
16
Camera.cpp
16
Camera.cpp
@@ -111,12 +111,12 @@ vector3 TCamera::GetDirection()
|
||||
|
||||
return (Normalize(Vec));
|
||||
}
|
||||
/*
|
||||
|
||||
bool TCamera::SetMatrix()
|
||||
{
|
||||
glRotated( -Roll * 180.0f / M_PI, 0, 0, 1 ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
|
||||
glRotated( -Pitch * 180.0f / M_PI, 1, 0, 0 );
|
||||
glRotated( -Yaw * 180.0f / M_PI, 0, 1, 0 ); // w zewnętrznym widoku: kierunek patrzenia
|
||||
glRotated( -Roll * 180.0 / M_PI, 0.0, 0.0, 1.0 ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
|
||||
glRotated( -Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0 );
|
||||
glRotated( -Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // w zewnętrznym widoku: kierunek patrzenia
|
||||
|
||||
if( Type == tp_Follow )
|
||||
{
|
||||
@@ -132,7 +132,7 @@ bool TCamera::SetMatrix()
|
||||
Global::SetCameraPosition(Pos); // było +pOffset
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
@@ -157,9 +157,9 @@ bool TCamera::SetMatrix( glm::mat4 &Matrix ) {
|
||||
void TCamera::SetCabMatrix(vector3 &p)
|
||||
{ // ustawienie widoku z kamery bez przesunięcia robionego przez OpenGL - nie powinno tak trząść
|
||||
|
||||
glRotated(-Roll * 180.0f / M_PI, 0, 0, 1);
|
||||
glRotated(-Pitch * 180.0f / M_PI, 1, 0, 0);
|
||||
glRotated(-Yaw * 180.0f / M_PI, 0, 1, 0); // w zewnętrznym widoku: kierunek patrzenia
|
||||
glRotated(-Roll * 180.0 / M_PI, 0.0, 0.0, 1.0);
|
||||
glRotated(-Pitch * 180.0 / M_PI, 1.0, 0.0, 0.0);
|
||||
glRotated(-Yaw * 180.0 / M_PI, 0.0, 1.0, 0.0); // w zewnętrznym widoku: kierunek patrzenia
|
||||
if (Type == tp_Follow)
|
||||
gluLookAt(Pos.x - 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
|
||||
|
||||
2
Camera.h
2
Camera.h
@@ -48,9 +48,7 @@ class TCamera
|
||||
void Update();
|
||||
vector3 GetDirection();
|
||||
// vector3 inline GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; };
|
||||
/*
|
||||
bool SetMatrix();
|
||||
*/
|
||||
bool SetMatrix(glm::mat4 &Matrix);
|
||||
void SetCabMatrix( vector3 &p );
|
||||
void RaLook();
|
||||
|
||||
@@ -36,9 +36,6 @@ class TMtableTime; // czas dla danego posterunku
|
||||
};
|
||||
|
||||
class TController; // obiekt sterujący pociągiem (AI)
|
||||
#ifdef EU07_USE_OLD_TNAMES_CLASS
|
||||
class TNames; // obiekt sortujący nazwy
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{ // binarne odpowiedniki komend w komórce pamięci
|
||||
|
||||
93
Driver.cpp
93
Driver.cpp
@@ -87,7 +87,7 @@ const double HardAcceleration = 0.9;
|
||||
const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu
|
||||
bool WriteLogFlag = false;
|
||||
|
||||
string StopReasonTable[] = {
|
||||
std::string StopReasonTable[] = {
|
||||
// przyczyny zatrzymania ruchu AI
|
||||
"", // stopNone, //nie ma powodu - powinien jechać
|
||||
"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...
|
||||
fVelNext = 30.0; // uzależnić prędkość od promienia; albo niech będzie
|
||||
// ograniczona w skrzyżowaniu (velocity z ujemną wartością)
|
||||
if ((iFlags & spElapsed) == 0) // jeśli nie wjechał
|
||||
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
|
||||
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( ( iFlags & spElapsed ) == 0 ) {
|
||||
// jeśli nie wjechał
|
||||
if( false == trTrack->Dynamics.empty() ) {
|
||||
if( Global::iWriteLogEnabled & 8 ) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
// 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 )
|
||||
&& ( false == trTrack->Dynamics.empty() ) ) {
|
||||
// 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
|
||||
}
|
||||
#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
|
||||
// już semafora)
|
||||
#if LOGSTOPS
|
||||
WriteLog(pVehicle->asName + " as " + TrainParams->TrainName + ": at " +
|
||||
std::to_string(GlobalTime->hh) + ":" + std::to_string(GlobalTime->mm) +
|
||||
" skipped " + asNextStop); // informacja
|
||||
WriteLog(
|
||||
pVehicle->asName + " as " + TrainParams->TrainName
|
||||
+ ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute)
|
||||
+ " skipped " + asNextStop); // informacja
|
||||
#endif
|
||||
fLastStopExpDist = mvOccupied->DistCounter + 0.250 +
|
||||
0.001 * fLength; // przy jakim dystansie (stanie
|
||||
// licznika) ma przesunąć na
|
||||
// następny postój
|
||||
TrainParams->UpdateMTable(
|
||||
GlobalTime->hh, GlobalTime->mm, asNextStop);
|
||||
// przy jakim dystansie (stanie licznika) ma przesunąć na następny postój
|
||||
fLastStopExpDist = mvOccupied->DistCounter + 0.250 + 0.001 * fLength;
|
||||
TrainParams->UpdateMTable( Simulation::Time, asNextStop );
|
||||
TrainParams->StationIndexInc(); // przejście do następnej
|
||||
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ł
|
||||
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
|
||||
// opóźnia również kierownika
|
||||
}
|
||||
if (TrainParams->UpdateMTable(
|
||||
GlobalTime->hh, GlobalTime->mm, asNextStop) )
|
||||
if (TrainParams->UpdateMTable( Simulation::Time, asNextStop) )
|
||||
{ // to się wykona tylko raz po zatrzymaniu na W4
|
||||
if (TrainParams->CheckTrainLatency() < 0.0)
|
||||
iDrivigFlags |= moveLate; // odnotowano spóźnienie
|
||||
@@ -1002,7 +976,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
if (TrainParams->StationIndex < TrainParams->StationCount)
|
||||
{ // 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
|
||||
/* potencjalny problem z ruszaniem z w4
|
||||
if (TrainParams->CheckTrainLatency() < 0)
|
||||
@@ -1019,10 +993,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
asNextStop = TrainParams->NextStop(); // pobranie kolejnego miejsca zatrzymania
|
||||
// TableClear(); //aby od nowa sprawdziło W4 z inną nazwą już - to nie jest dobry pomysł
|
||||
#if LOGSTOPS
|
||||
WriteLog(pVehicle->asName + " as " + TrainParams->TrainName +
|
||||
": at " + std::to_string(GlobalTime->hh) + ":" +
|
||||
std::to_string(GlobalTime->mm) + " next " +
|
||||
asNextStop); // informacja
|
||||
WriteLog(
|
||||
pVehicle->asName + " as " + TrainParams->TrainName
|
||||
+ ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute)
|
||||
+ " next " + asNextStop); // informacja
|
||||
#endif
|
||||
if (int(floor(sSpeedTable[i].evEvent->ValueGet(1))) & 1)
|
||||
iDrivigFlags |= moveStopHere; // nie podjeżdżać do semafora,
|
||||
@@ -1046,10 +1020,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
||||
else
|
||||
{ // jeśli dojechaliśmy do końca rozkładu
|
||||
#if LOGSTOPS
|
||||
WriteLog(pVehicle->asName + " as " + TrainParams->TrainName +
|
||||
": at " + std::to_string(GlobalTime->hh) + ":" +
|
||||
std::to_string(GlobalTime->mm) +
|
||||
" end of route."); // informacja
|
||||
WriteLog(
|
||||
pVehicle->asName + " as " + TrainParams->TrainName
|
||||
+ ": at " + std::to_string(Simulation::Time.data().wHour) + ":" + std::to_string(Simulation::Time.data().wMinute)
|
||||
+ " end of route."); // informacja
|
||||
#endif
|
||||
asNextStop = TrainParams->NextStop(); // informacja o końcu trasy
|
||||
TrainParams->NewName("none"); // czyszczenie nieaktualnego rozkładu
|
||||
@@ -1504,10 +1478,10 @@ TController::TController(bool AI, TDynamicObject *NewControll, bool InitPsyche,
|
||||
|
||||
if( WriteLogFlag ) {
|
||||
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 );
|
||||
#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] "
|
||||
"BrakeForce [kN] BrakePress [MPa] PipePress [MPa] "
|
||||
"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)
|
||||
else
|
||||
{ // 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)
|
||||
{ // to skład pasażerski - nastawianie pasażerskiego
|
||||
ustaw += (g && (r < g + p)) ? bdelay_P : bdelay_R;
|
||||
@@ -2891,8 +2865,7 @@ bool TController::PutCommand(std::string NewCommand, double NewValue1, double Ne
|
||||
}
|
||||
else
|
||||
{ // inicjacja pierwszego przystanku i pobranie jego nazwy
|
||||
TrainParams->UpdateMTable(GlobalTime->hh, GlobalTime->mm,
|
||||
TrainParams->NextStationName);
|
||||
TrainParams->UpdateMTable( Simulation::Time, TrainParams->NextStationName );
|
||||
TrainParams->StationIndexInc(); // przejście do następnej
|
||||
iStationStart = TrainParams->StationIndex;
|
||||
asNextStop = TrainParams->NextStop();
|
||||
@@ -4927,7 +4900,7 @@ void TController::OrdersInit(double fVel)
|
||||
// Ale mozna by je zapodac ze scenerii
|
||||
};
|
||||
|
||||
string TController::StopReasonText()
|
||||
std::string TController::StopReasonText()
|
||||
{ // informacja tekstowa o przyczynie zatrzymania
|
||||
if (eStopReason != 7) // zawalidroga będzie inaczej
|
||||
return StopReasonTable[eStopReason];
|
||||
@@ -4952,15 +4925,6 @@ double TController::Distance(vector3 &p1,vector3 &n,vector3 &p2)
|
||||
|
||||
bool TController::BackwardTrackBusy(TTrack *Track)
|
||||
{ // 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() ) {
|
||||
for( auto dynamic : Track->Dynamics ) {
|
||||
if( dynamic->ctOwner != this ) {
|
||||
@@ -4970,7 +4934,6 @@ bool TController::BackwardTrackBusy(TTrack *Track)
|
||||
}
|
||||
}
|
||||
return false; // wolny
|
||||
#endif
|
||||
};
|
||||
|
||||
TEvent * TController::CheckTrackEventBackward(double fDirection, TTrack *Track)
|
||||
@@ -5435,5 +5398,5 @@ void TController::RouteSwitch(int d)
|
||||
};
|
||||
std::string TController::OwnerName()
|
||||
{
|
||||
return pVehicle ? pVehicle->MoverParameters->Name : string("none");
|
||||
return ( pVehicle ? pVehicle->MoverParameters->Name : "none" );
|
||||
};
|
||||
|
||||
188
DynObj.cpp
188
DynObj.cpp
@@ -950,69 +950,15 @@ double ABuAcos(const vector3 &calc_temp)
|
||||
return atan2(-calc_temp.x, calc_temp.z); // Ra: tak prościej
|
||||
}
|
||||
|
||||
TDynamicObject * TDynamicObject::ABuFindNearestObject(TTrack *Track,
|
||||
TDynamicObject *MyPointer,
|
||||
int &CouplNr)
|
||||
{ // zwraca wskaznik do obiektu znajdujacego sie na torze
|
||||
// (Track), którego sprzęg jest najblizszy
|
||||
// kamerze
|
||||
TDynamicObject * TDynamicObject::ABuFindNearestObject(TTrack *Track, TDynamicObject *MyPointer, int &CouplNr)
|
||||
{
|
||||
// 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
|
||||
// WE: Track - tor, na ktorym odbywa sie poszukiwanie
|
||||
// MyPointer - wskaznik do obiektu szukajacego
|
||||
// WY: CouplNr - który sprzęg znalezionego obiektu jest bliższy kamerze
|
||||
|
||||
// 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 ) {
|
||||
|
||||
if( CouplNr == -2 ) {
|
||||
@@ -1038,7 +984,6 @@ TDynamicObject * TDynamicObject::ABuFindNearestObject(TTrack *Track,
|
||||
}
|
||||
// empty track or nothing found
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
TDynamicObject * TDynamicObject::ABuScanNearestObject(TTrack *Track, double ScanDir,
|
||||
@@ -1160,21 +1105,13 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
|
||||
|
||||
// WY: wskaznik do znalezionego obiektu.
|
||||
// CouplFound - nr sprzegu znalezionego obiektu
|
||||
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
|
||||
if (Track->iNumDynamics > 0)
|
||||
#else
|
||||
if( false == Track->Dynamics.empty() )
|
||||
#endif
|
||||
{ // sens szukania na tym torze jest tylko, gdy są na nim pojazdy
|
||||
double MyTranslation; // pozycja szukającego na torze
|
||||
double MinDist = Track->Length(); // najmniejsza znaleziona odleglość
|
||||
// (zaczynamy od długości toru)
|
||||
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;
|
||||
#endif
|
||||
// if (Track->iNumDynamics>1)
|
||||
// iMinDist+=0; //tymczasowo pułapka
|
||||
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
|
||||
if (ScanDir >= 0)
|
||||
{ // 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 ) {
|
||||
// pętla po pojazdach
|
||||
if( dynamic == this ) {
|
||||
@@ -1277,56 +1166,9 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
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 ) {
|
||||
|
||||
if( dynamic == this ) { continue; }
|
||||
@@ -1362,14 +1204,9 @@ TDynamicObject * TDynamicObject::ABuFindObject(TTrack *Track, int ScanDir,
|
||||
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
|
||||
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
|
||||
return ( iMinDist >= 0 ) ? Track->Dynamics[ iMinDist ] : NULL;
|
||||
#else
|
||||
return collider;
|
||||
#endif
|
||||
}
|
||||
dist += Track->Length(); // doliczenie długości odcinka do przeskanowanej
|
||||
// odległości
|
||||
@@ -2451,19 +2288,18 @@ void TDynamicObject::AttachPrev(TDynamicObject *Object, int iType)
|
||||
Object->NextConnected = this; // on ma nas z tyłu
|
||||
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,
|
||||
// światła w rozrządczym zależą od
|
||||
// stanu w silnikowym
|
||||
if (MoverParameters->Couplers[iDirection].AllowedFlag &
|
||||
ctrain_depot) // gdy sprzęgi łączone warsztatowo (powiedzmy)
|
||||
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
|
||||
// światła w rozrządczym zależą od stanu w silnikowym
|
||||
if (MoverParameters->Couplers[iDirection].AllowedFlag & ctrain_depot) // gdy sprzęgi łączone warsztatowo (powiedzmy)
|
||||
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) &&
|
||||
(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
|
||||
// załączane, a w tym bez tylko widoczne
|
||||
Object->iLights = MoverParameters->iLights; // to w tym z mocą będą światła załączane, a w tym bez tylko widoczne
|
||||
*/
|
||||
return;
|
||||
// SetPneumatic(1,1); //Ra: to i tak się nie wykonywało po return
|
||||
// SetPneumatic(1,0);
|
||||
|
||||
20
EvLaunch.cpp
20
EvLaunch.cpp
@@ -36,21 +36,13 @@ TEventLauncher::TEventLauncher()
|
||||
DeltaTime = -1;
|
||||
UpdatedTime = 0;
|
||||
fVal1 = fVal2 = 0;
|
||||
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
|
||||
szText = NULL;
|
||||
#endif
|
||||
iHour = iMinute = -1; // takiego czasu nigdy nie będzie
|
||||
dRadius = 0;
|
||||
Event1 = Event2 = NULL;
|
||||
MemCell = NULL;
|
||||
iCheckMask = 0;
|
||||
}
|
||||
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
|
||||
TEventLauncher::~TEventLauncher()
|
||||
{
|
||||
SafeDeleteArray(szText);
|
||||
}
|
||||
#endif
|
||||
|
||||
void TEventLauncher::Init()
|
||||
{
|
||||
}
|
||||
@@ -126,13 +118,7 @@ bool TEventLauncher::Load(cParser *parser)
|
||||
asMemCellName = token;
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
|
||||
SafeDeleteArray(szText);
|
||||
szText = new char[256];
|
||||
strcpy(szText, token.c_str());
|
||||
#else
|
||||
szText = token;
|
||||
#endif
|
||||
if (token != "*") //*=nie brać command pod uwagę
|
||||
iCheckMask |= conditional_memstring;
|
||||
parser->getTokens();
|
||||
@@ -189,9 +175,9 @@ bool TEventLauncher::Render()
|
||||
}
|
||||
else
|
||||
{ // 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
|
||||
if (UpdatedTime < 10)
|
||||
{
|
||||
|
||||
11
EvLaunch.h
11
EvLaunch.h
@@ -7,8 +7,7 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef EvLaunchH
|
||||
#define EvLaunchH
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "Classes.h"
|
||||
@@ -21,11 +20,7 @@ class TEventLauncher
|
||||
double UpdatedTime;
|
||||
double fVal1;
|
||||
double fVal2;
|
||||
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
|
||||
char * szText;
|
||||
#else
|
||||
std::string szText;
|
||||
#endif
|
||||
int iHour, iMinute; // minuta uruchomienia
|
||||
public:
|
||||
double dRadius;
|
||||
@@ -37,9 +32,6 @@ class TEventLauncher
|
||||
TMemCell *MemCell;
|
||||
int iCheckMask;
|
||||
TEventLauncher();
|
||||
#ifdef EU07_USE_OLD_TEVENTLAUNCHER_TEXT_ARRAY
|
||||
~TEventLauncher();
|
||||
#endif
|
||||
void Init();
|
||||
bool Load(cParser *parser);
|
||||
bool Render();
|
||||
@@ -47,4 +39,3 @@ class TEventLauncher
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
if (s == "condition")
|
||||
{ // jesli nie "endevent"
|
||||
@@ -623,14 +623,14 @@ void TEvent::AddToQuery(TEvent *e)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
string TEvent::CommandGet()
|
||||
std::string TEvent::CommandGet()
|
||||
{ // odczytanie komendy z eventu
|
||||
switch (Type)
|
||||
{ // to się wykonuje również składu jadącego bez obsługi
|
||||
case tp_GetValues:
|
||||
return string(Params[9].asMemCell->Text());
|
||||
return std::string(Params[9].asMemCell->Text());
|
||||
case tp_PutValues:
|
||||
return string(Params[0].asText);
|
||||
return std::string(Params[0].asText);
|
||||
}
|
||||
return ""; // inne eventy się nie liczą
|
||||
};
|
||||
|
||||
13
Globals.cpp
13
Globals.cpp
@@ -78,11 +78,12 @@ double Global::pCameraRotation;
|
||||
double Global::pCameraRotationDeg;
|
||||
std::vector<vector3> Global::FreeCameraInit;
|
||||
std::vector<vector3> Global::FreeCameraInitAngle;
|
||||
double Global::fFogStart = 1700;
|
||||
double Global::fFogEnd = 2000;
|
||||
float Global::Background[3] = {0.2f, 0.4f, 0.33f};
|
||||
GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f};
|
||||
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
|
||||
GLfloat Global::ambientDayLight[] = {0.40f, 0.40f, 0.45f, 1.0f}; // robocze
|
||||
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::iRailProFiltering = 5; // domyślne rozmywanie tekstur szyn
|
||||
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;
|
||||
GLint Global::iMaxTextureSize = 4096; // maksymalny rozmiar tekstury
|
||||
bool Global::bSmoothTraction = false; // wygładzanie drutów starym sposobem
|
||||
@@ -480,13 +480,6 @@ void Global::ConfigParse(cParser &Parser)
|
||||
Parser.getTokens( 1, false );
|
||||
Parser >> Global::AnisotropicFiltering;
|
||||
}
|
||||
else if( token == "usevbo" )
|
||||
{
|
||||
/*
|
||||
Parser.getTokens();
|
||||
Parser >> Global::bUseVBO;
|
||||
*/
|
||||
}
|
||||
else if (token == "feedbackmode")
|
||||
{
|
||||
|
||||
|
||||
@@ -218,6 +218,7 @@ class Global
|
||||
static float Background[3];
|
||||
static GLfloat AtmoColor[];
|
||||
static GLfloat FogColor[];
|
||||
static float Overcast;
|
||||
// static bool bTimeChange;
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
static opengl_light AmbientLight;
|
||||
@@ -248,7 +249,6 @@ class Global
|
||||
static int iRailProFiltering; // domyślne rozmywanie tekstury szyn
|
||||
static int iDynamicFiltering; // domyślne rozmywanie tekstur pojazdów
|
||||
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 int iFeedbackMode; // tryb pracy informacji zwrotnej
|
||||
static int iFeedbackPort; // dodatkowy adres dla informacji zwrotnych
|
||||
@@ -360,10 +360,9 @@ class Global
|
||||
|
||||
struct daylight_s
|
||||
{
|
||||
float3 position;
|
||||
float3 direction;
|
||||
float3 color;
|
||||
float3 ambient;
|
||||
glm::vec3 ambient;
|
||||
glm::vec3 direction;
|
||||
glm::vec3 color;
|
||||
float intensity;
|
||||
};
|
||||
|
||||
|
||||
764
Ground.cpp
764
Ground.cpp
File diff suppressed because it is too large
Load Diff
13
Ground.h
13
Ground.h
@@ -300,21 +300,12 @@ class TGround
|
||||
// TGroundNode *nLastOfType[TP_LAST]; //ostatnia
|
||||
TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe)
|
||||
int hh = 0,
|
||||
mm = 0,
|
||||
srh = 0,
|
||||
srm = 0,
|
||||
ssh = 0,
|
||||
ssm = 0; // ustawienia czasu
|
||||
mm = 0; // ustawienia czasu
|
||||
// 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;
|
||||
event_map m_eventmap;
|
||||
TNames<TGroundNode *> m_trackmap;
|
||||
#endif
|
||||
|
||||
light_array m_lights;
|
||||
light_array m_lights; // collection of dynamic light sources present in the scene
|
||||
|
||||
private: // metody prywatne
|
||||
bool EventConditon(TEvent *e);
|
||||
|
||||
83
MemCell.cpp
83
MemCell.cpp
@@ -28,37 +28,20 @@ http://mozilla.org/MPL/2.0/.
|
||||
TMemCell::TMemCell(vector3 *p)
|
||||
{
|
||||
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 =
|
||||
p ? *p : vector3(0, 0, 0); // ustawienie współrzędnych, bo do TGroundNode nie ma dostępu
|
||||
bCommand = false; // komenda wysłana
|
||||
OnSent = NULL;
|
||||
}
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
TMemCell::~TMemCell()
|
||||
{
|
||||
SafeDeleteArray(szText);
|
||||
}
|
||||
#endif
|
||||
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 )
|
||||
#endif
|
||||
{
|
||||
if (CheckMask & update_memadd)
|
||||
{ // dodawanie wartości
|
||||
if( TestFlag( CheckMask, update_memstring ) )
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
strcat( szText, szNewText );
|
||||
#else
|
||||
szText += szNewText;
|
||||
#endif
|
||||
if (TestFlag(CheckMask, update_memval1))
|
||||
fValue1 += fNewValue1;
|
||||
if (TestFlag(CheckMask, update_memval2))
|
||||
@@ -67,11 +50,7 @@ void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValu
|
||||
else
|
||||
{
|
||||
if( TestFlag( CheckMask, update_memstring ) )
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
strcpy( szText, szNewText );
|
||||
#else
|
||||
szText = szNewText;
|
||||
#endif
|
||||
if (TestFlag(CheckMask, update_memval1))
|
||||
fValue1 = fNewValue1;
|
||||
if (TestFlag(CheckMask, update_memval2))
|
||||
@@ -83,56 +62,32 @@ void TMemCell::UpdateValues( std::string const &szNewText, double const fNewValu
|
||||
|
||||
TCommandType TMemCell::CommandCheck()
|
||||
{ // rozpoznanie komendy
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
if (strcmp(szText, "SetVelocity") == 0) // najpopularniejsze
|
||||
#else
|
||||
if( szText == "SetVelocity" ) // najpopularniejsze
|
||||
#endif
|
||||
{
|
||||
eCommand = cm_SetVelocity;
|
||||
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
|
||||
#endif
|
||||
{
|
||||
eCommand = cm_ShuntVelocity;
|
||||
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ę
|
||||
#endif
|
||||
{
|
||||
eCommand = cm_ChangeDirection;
|
||||
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ę
|
||||
#endif
|
||||
{
|
||||
eCommand = cm_OutsideStation;
|
||||
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
|
||||
#endif
|
||||
{
|
||||
eCommand = cm_PassengerStopPoint;
|
||||
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ć
|
||||
#endif
|
||||
{
|
||||
eCommand = cm_SetProximityVelocity;
|
||||
bCommand = false; // ta komenda nie jest wysyłana
|
||||
@@ -149,14 +104,7 @@ bool TMemCell::Load(cParser *parser)
|
||||
{
|
||||
std::string token;
|
||||
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;
|
||||
#endif
|
||||
parser->getTokens( 2, false );
|
||||
*parser
|
||||
>> fValue1
|
||||
@@ -179,32 +127,6 @@ void TMemCell::PutCommand(TController *Mech, vector3 *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 ) {
|
||||
// porównanie zawartości komórki pamięci z podanymi wartościami
|
||||
if( TestFlag( CheckMask, conditional_memstring ) ) {
|
||||
@@ -224,10 +146,9 @@ bool TMemCell::Compare( std::string const &szTestText, double const fTestValue1,
|
||||
}
|
||||
}
|
||||
// tekst zgodny, porównać resztę
|
||||
return ( ( !TestFlag( CheckMask, conditional_memval1 ) || ( fValue1 == fTestValue1 ) ) &&
|
||||
( !TestFlag( CheckMask, conditional_memval2 ) || ( fValue2 == fTestValue2 ) ) );
|
||||
return ( ( !TestFlag( CheckMask, conditional_memval1 ) || ( fValue1 == fTestValue1 ) )
|
||||
&& ( !TestFlag( CheckMask, conditional_memval2 ) || ( fValue2 == fTestValue2 ) ) );
|
||||
};
|
||||
#endif
|
||||
|
||||
bool TMemCell::Render()
|
||||
{
|
||||
|
||||
38
MemCell.h
38
MemCell.h
@@ -7,56 +7,31 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef MemCellH
|
||||
#define MemCellH
|
||||
#pragma once
|
||||
|
||||
#include "Classes.h"
|
||||
#include "dumb3d.h"
|
||||
using namespace Math3D;
|
||||
using namespace std;
|
||||
|
||||
class TMemCell
|
||||
{
|
||||
private:
|
||||
vector3 vPosition;
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
char *szText;
|
||||
#else
|
||||
Math3D::vector3 vPosition;
|
||||
std::string szText;
|
||||
#endif
|
||||
double fValue1;
|
||||
double fValue2;
|
||||
TCommandType eCommand;
|
||||
bool bCommand; // czy zawiera komendę dla zatrzymanego AI
|
||||
TEvent *OnSent; // event dodawany do kolejki po wysłaniu komendy zatrzymującej skład
|
||||
public:
|
||||
string
|
||||
asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
|
||||
TMemCell(vector3 *p);
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
~TMemCell();
|
||||
#endif
|
||||
std::string asTrackName; // McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
|
||||
TMemCell( Math3D::vector3 *p );
|
||||
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 );
|
||||
#endif
|
||||
bool Load(cParser *parser);
|
||||
void PutCommand(TController *Mech, vector3 *Loc);
|
||||
bool Compare( char const *szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask );
|
||||
#ifndef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
void PutCommand( TController *Mech, Math3D::vector3 *Loc );
|
||||
bool Compare( std::string const &szTestText, double const fTestValue1, double const fTestValue2, int const CheckMask );
|
||||
#endif
|
||||
bool Render();
|
||||
#ifdef EU07_USE_OLD_TMEMCELL_TEXT_ARRAY
|
||||
inline char * Text()
|
||||
{
|
||||
return szText;
|
||||
};
|
||||
#else
|
||||
inline std::string const &Text() { return szText; }
|
||||
#endif
|
||||
inline double Value1()
|
||||
{
|
||||
return fValue1;
|
||||
@@ -65,7 +40,7 @@ class TMemCell
|
||||
{
|
||||
return fValue2;
|
||||
};
|
||||
inline vector3 Position()
|
||||
inline Math3D::vector3 Position()
|
||||
{
|
||||
return vPosition;
|
||||
};
|
||||
@@ -84,4 +59,3 @@ class TMemCell
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
183
Model3d.cpp
183
Model3d.cpp
@@ -317,15 +317,21 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
|
||||
}
|
||||
std::string discard;
|
||||
parser.getTokens(13, false);
|
||||
parser >> fNearAttenStart >> discard >> fNearAttenEnd >> discard >> bUseNearAtten >>
|
||||
discard >> iFarAttenDecay >> discard >> fFarDecayRadius >> discard >>
|
||||
fCosFalloffAngle // kąt liczony dla średnicy, a nie promienia
|
||||
parser
|
||||
>> fNearAttenStart
|
||||
>> 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
|
||||
fCosFalloffAngle = cos(DegToRad(0.5 * fCosFalloffAngle));
|
||||
fCosHotspotAngle = cos(DegToRad(0.5 * fCosHotspotAngle));
|
||||
fCosFalloffAngle = std::cos( DegToRad( 0.5f * fCosFalloffAngle ) );
|
||||
fCosHotspotAngle = std::cos( DegToRad( 0.5f * fCosHotspotAngle ) );
|
||||
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)
|
||||
{
|
||||
@@ -637,91 +643,8 @@ float8 *TSubModel::TrianglePtr(int tex, int pos, int *la, int *ld, int *ls)
|
||||
};
|
||||
|
||||
void TSubModel::DisplayLists()
|
||||
{ // utworznie po jednej skompilowanej liście dla
|
||||
// każdego submodelu
|
||||
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();
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
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));
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
@@ -1007,18 +930,20 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
matrix4x4 mat; // potrzebujemy współrzędne przesunięcia środka układu
|
||||
// współrzędnych submodelu
|
||||
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
|
||||
glTranslatef(gdzie.x, gdzie.y, gdzie.z); // początek układu zostaje bez
|
||||
// zmian
|
||||
glRotated(atan2(gdzie.x, gdzie.z) * 180.0 / M_PI, 0.0, 1.0,
|
||||
0.0); // jedynie obracamy w pionie o kąt
|
||||
*/ //m7todo: restore
|
||||
*/
|
||||
//m7todo: restore
|
||||
}
|
||||
break;
|
||||
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;
|
||||
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
|
||||
@@ -1052,6 +977,7 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
void TSubModel::RenderDL()
|
||||
{ // główna procedura renderowania przez DL
|
||||
return;
|
||||
@@ -1275,8 +1201,11 @@ void TSubModel::RenderVBO(glm::mat4 m)
|
||||
}
|
||||
else if (eType == TP_FREESPOTLIGHT)
|
||||
{ // wersja VBO
|
||||
/*
|
||||
matrix4x4 mat; // macierz opisuje układ renderowania względem kamery
|
||||
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
|
||||
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));
|
||||
@@ -1398,7 +1327,7 @@ void TSubModel::RenderAlphaVBO(glm::mat4 m)
|
||||
if (iAlpha & iFlags & 0x2F000000)
|
||||
Next->RenderAlphaVBO(m);
|
||||
}; // RaRenderAlpha
|
||||
|
||||
#endif
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void TSubModel::RaArrayFill(CVertNormTex *Vert)
|
||||
@@ -1956,8 +1885,6 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
|
||||
pName = "";
|
||||
if (iTexture > 0)
|
||||
{ // obsługa stałej tekstury
|
||||
// TextureID=TTexturesManager::GetTextureID(t->String(TextureID));
|
||||
// asTexture=AnsiString(t->String(iTexture));
|
||||
pTexture = t->at(iTexture);
|
||||
if (pTexture.find_last_of("/\\") == std::string::npos)
|
||||
pTexture.insert(0, Global::asCurrentTexturePath);
|
||||
@@ -1966,9 +1893,17 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v,
|
||||
}
|
||||
else
|
||||
TextureID = iTexture;
|
||||
|
||||
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;
|
||||
Vertices = v + iVboPtr;
|
||||
// if (!iNumVerts) eType=-1; //tymczasowo zmiana typu, żeby się nie
|
||||
@@ -2074,22 +2009,15 @@ void TModel3d::Init()
|
||||
Root->AdjustDist(); // aktualizacja odległości faz LoD, zależnie od
|
||||
// rozdzielczości pionowej oraz multisamplingu
|
||||
*/
|
||||
if (Global::bUseVBO)
|
||||
{
|
||||
if (!m_pVNT) // jeśli nie ma jeszcze tablicy (wczytano z pliku
|
||||
// tekstowego)
|
||||
{ // tworzenie tymczasowej tablicy z wierzchołkami całego modelu
|
||||
MakeArray(iNumVerts); // tworzenie tablic dla VBO
|
||||
Root->RaArrayFill(m_pVNT); // wypełnianie tablicy
|
||||
BuildVBOs(); // tworzenie VBO i usuwanie tablicy z pamięci
|
||||
}
|
||||
else
|
||||
BuildVBOs(false); // tworzenie VBO bez usuwania tablicy z pamięci
|
||||
if (!m_pVNT) // jeśli nie ma jeszcze tablicy (wczytano z pliku
|
||||
// tekstowego)
|
||||
{ // tworzenie tymczasowej tablicy z wierzchołkami całego modelu
|
||||
MakeArray(iNumVerts); // tworzenie tablic dla VBO
|
||||
Root->RaArrayFill(m_pVNT); // wypełnianie tablicy
|
||||
BuildVBOs(); // tworzenie VBO i usuwanie tablicy z pamięci
|
||||
}
|
||||
else
|
||||
{ // przygotowanie skompilowanych siatek dla DisplayLists
|
||||
Root->DisplayLists(); // tworzenie skompilowanej listy dla submodelu
|
||||
}
|
||||
BuildVBOs(false); // tworzenie VBO bez usuwania tablicy z pamięci
|
||||
// if (Root->TextureID) //o ile ma teksturę
|
||||
// Root->iFlags|=0x80; //konieczność ustawienia tekstury
|
||||
}
|
||||
@@ -2122,7 +2050,7 @@ void TModel3d::RenderAlpha(double fSquareDistance, texture_manager::size_type *R
|
||||
Root->RenderAlphaDL();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void TModel3d::RaRender(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
|
||||
{ // renderowanie specjalne, np. kabiny
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2205,7 +2133,7 @@ void TModel3d::RenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manager:
|
||||
Root->RenderAlphaDL();
|
||||
glPopMatrix();
|
||||
};
|
||||
#endif
|
||||
|
||||
void TModel3d::RaRender(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
|
||||
{ // nieprzezroczyste, VBO
|
||||
glPushMatrix();
|
||||
@@ -2261,7 +2189,7 @@ void TModel3d::RaRenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manage
|
||||
}
|
||||
glPopMatrix();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 2012-02 funkcje do tworzenia terenu z E3D
|
||||
@@ -2313,9 +2241,8 @@ void TModel3d::TerrainRenderVBO(int n)
|
||||
TSubModel *r = Root;
|
||||
while (r)
|
||||
{
|
||||
if (r->iVisible ==
|
||||
n) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
|
||||
r->RenderVBO(glm::make_mat4(mv)); // sub kolejne (Next) się nie wyrenderują
|
||||
if (r->iVisible == n) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
|
||||
GfxRenderer.Render(r); // sub kolejne (Next) się nie wyrenderują
|
||||
r = r->NextGet();
|
||||
}
|
||||
EndVBO();
|
||||
|
||||
@@ -182,8 +182,7 @@ private:
|
||||
int iFarAttenDecay; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R)
|
||||
float fFarDecayRadius; // normalizacja j.w.
|
||||
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
|
||||
// światła
|
||||
float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
|
||||
float fCosViewAngle; // cos kata pod jakim sie teraz patrzy
|
||||
|
||||
TSubModel *Next;
|
||||
@@ -256,10 +255,12 @@ public:
|
||||
void SetRotateIK1(float3 vNewAngles);
|
||||
TSubModel * GetFromName(std::string const &search, bool i = true);
|
||||
TSubModel * GetFromName(char const *search, bool i = true);
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
void RenderDL();
|
||||
void RenderAlphaDL();
|
||||
void RenderVBO(glm::mat4 m);
|
||||
void RenderAlphaVBO(glm::mat4 m);
|
||||
void RenderVBO();
|
||||
void RenderAlphaVBO();
|
||||
#endif
|
||||
// inline matrix4x4* GetMatrix() {return dMatrix;};
|
||||
inline float4x4 * GetMatrix()
|
||||
{
|
||||
|
||||
176
Names.cpp
176
Names.cpp
@@ -11,179 +11,3 @@ http://mozilla.org/MPL/2.0/.
|
||||
#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
82
Names.h
@@ -1,4 +1,3 @@
|
||||
#pragma once
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
@@ -8,12 +7,12 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#ifndef EU07_USE_OLD_TNAMES_CLASS
|
||||
|
||||
template <typename _Pointer>
|
||||
template <typename _Type>
|
||||
class TNames {
|
||||
|
||||
public:
|
||||
@@ -27,7 +26,7 @@ public:
|
||||
// methods:
|
||||
// dodanie obiektu z wskaźnikiem. updates data field if the object already exists. returns true for insertion, false for update
|
||||
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 );
|
||||
if( lookup.second == false ) {
|
||||
@@ -41,7 +40,7 @@ public:
|
||||
}
|
||||
}
|
||||
// returns pointer associated with provided label, or nullptr if there's no match
|
||||
_Pointer
|
||||
_Type
|
||||
Find( int const Type, std::string const &Name ) {
|
||||
|
||||
auto const &map = find_map( Type );
|
||||
@@ -52,78 +51,17 @@ public:
|
||||
|
||||
private:
|
||||
// types:
|
||||
typedef std::unordered_map<std::string, _Pointer> pointer_map;
|
||||
typedef std::unordered_map<int, pointer_map> pointermap_map;
|
||||
typedef std::unordered_map<std::string, _Type> type_map;
|
||||
typedef std::unordered_map<int, type_map> typemap_map;
|
||||
|
||||
// methods:
|
||||
// returns database stored with specified type key; creates new database if needed.
|
||||
pointer_map &
|
||||
type_map &
|
||||
find_map( int const Type ) {
|
||||
|
||||
return m_maps.emplace( Type, pointer_map() ).first->second;
|
||||
return m_maps.emplace( Type, type_map() ).first->second;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@@ -307,7 +307,7 @@ void TPythonScreenRenderer::updateTexture()
|
||||
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
}
|
||||
// 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
|
||||
GLenum status = glGetError();
|
||||
|
||||
@@ -18,7 +18,7 @@ double ResourceManager::_lastReport = 0.0f;
|
||||
|
||||
void ResourceManager::Register(Resource *resource)
|
||||
{
|
||||
_resources.push_back(resource);
|
||||
_resources.emplace_back(resource);
|
||||
};
|
||||
|
||||
void ResourceManager::Unregister(Resource *resource)
|
||||
|
||||
62
Segment.cpp
62
Segment.cpp
@@ -42,10 +42,12 @@ TSegment::~TSegment()
|
||||
SafeDeleteArray(fTsBuffer);
|
||||
};
|
||||
|
||||
bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1,
|
||||
double fNewRoll2)
|
||||
bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1, double fNewRoll2)
|
||||
{ // wersja dla prostego - wyliczanie punktów kontrolnych
|
||||
vector3 dir;
|
||||
|
||||
// NOTE: we're enforcing division also for straight track, to ensure dense enough mesh for per-vertex lighting
|
||||
/*
|
||||
if (fNewRoll1 == fNewRoll2)
|
||||
{ // faktyczny prosty
|
||||
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);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{ // 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
|
||||
return TSegment::Init(NewPoint1, NewPoint1 + dir, NewPoint2 - dir, NewPoint2, fNewStep,
|
||||
fNewRoll1, fNewRoll2, true);
|
||||
return TSegment::Init(
|
||||
NewPoint1, NewPoint1 + dir,
|
||||
NewPoint2 - dir, NewPoint2,
|
||||
fNewStep, fNewRoll1, fNewRoll2, true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,40 +118,31 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
|
||||
fStep = fNewStep;
|
||||
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);
|
||||
return false; // zerowe nie mogą być
|
||||
}
|
||||
fStoop = atan2((Point2.y - Point1.y),
|
||||
fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
||||
SafeDeleteArray(fTsBuffer);
|
||||
/*
|
||||
if ((bCurve) && (fStep > 0))
|
||||
*/
|
||||
// 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;
|
||||
int i = 0;
|
||||
iSegCount = ceil(fLength / fStep); // potrzebne do VBO
|
||||
// fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
|
||||
fTsBuffer = new double[iSegCount + 1];
|
||||
fTsBuffer[0] = 0; /* TODO : fix fTsBuffer */
|
||||
while (s < fLength)
|
||||
{
|
||||
i++;
|
||||
s += fStep;
|
||||
if (s > fLength)
|
||||
s = fLength;
|
||||
fTsBuffer[i] = GetTFromS(s);
|
||||
|
||||
if( ( bCurve ) && ( fStep > 0 ) ) {
|
||||
if( fStep > 0 ) { // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
|
||||
double s = 0;
|
||||
int i = 0;
|
||||
iSegCount = ceil( fLength / fStep ); // potrzebne do VBO
|
||||
// fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
|
||||
fTsBuffer = new double[ iSegCount + 1 ];
|
||||
fTsBuffer[ 0 ] = 0; /* TODO : fix fTsBuffer */
|
||||
while( s < fLength ) {
|
||||
i++;
|
||||
s += fStep;
|
||||
if( s > fLength )
|
||||
s = fLength;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -224,7 +220,7 @@ double TSegment::GetTFromS(double s)
|
||||
// Newton's method failed. If this happens, increase iterations or
|
||||
// tolerance or integration accuracy.
|
||||
// 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);
|
||||
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);
|
||||
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 (!j) // to dla pierwszego punktu
|
||||
{
|
||||
|
||||
13
Texture.cpp
13
Texture.cpp
@@ -66,6 +66,8 @@ opengl_texture::load() {
|
||||
fail:
|
||||
data_state = resource_state::failed;
|
||||
ErrorLog( "Failed to load texture \"" + name + "\"" );
|
||||
// NOTE: temporary workaround for texture assignment errors
|
||||
id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -252,6 +254,7 @@ opengl_texture::load_DDS() {
|
||||
data_width /= 2;
|
||||
data_height /= 2;
|
||||
--data_mapcount;
|
||||
WriteLog( "Texture size exceeds specified limits, skipping mipmap level" );
|
||||
};
|
||||
|
||||
if( data_mapcount <= 0 ) {
|
||||
@@ -580,9 +583,9 @@ opengl_texture::create() {
|
||||
dataheight = std::max( dataheight / 2, 1 );
|
||||
}
|
||||
else {
|
||||
// uncompressed texture data
|
||||
// uncompressed texture data. have the gfx card do the compression as it sees fit
|
||||
::glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8,
|
||||
GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA,
|
||||
data_width, data_height, 0,
|
||||
data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[ 0 ] );
|
||||
}
|
||||
@@ -676,6 +679,7 @@ opengl_texture::downsize( GLuint const Format ) {
|
||||
break;
|
||||
}
|
||||
|
||||
WriteLog( "Texture size exceeds specified limits, downsampling data" );
|
||||
switch( Format ) {
|
||||
|
||||
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
|
||||
if( Id != 0 ) {
|
||||
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD
|
||||
::glBindTexture( GL_TEXTURE_2D, Id );
|
||||
m_activetexture = 0;
|
||||
// NOTE: we could bind dedicated 'error' texture here if the id isn't valid
|
||||
::glBindTexture( GL_TEXTURE_2D, Texture(Id).id );
|
||||
m_activetexture = Texture(Id).id;
|
||||
#else
|
||||
if( Texture( Id ).bind() == resource_state::good ) {
|
||||
m_activetexture = Id;
|
||||
|
||||
4
Timer.h
4
Timer.h
@@ -7,8 +7,7 @@ obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef TimerH
|
||||
#define TimerH
|
||||
#pragma once
|
||||
|
||||
namespace Timer
|
||||
{
|
||||
@@ -36,4 +35,3 @@ void UpdateTimers(bool pause);
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
||||
299
Track.cpp
299
Track.cpp
@@ -77,8 +77,8 @@ TIsolated::TIsolated()
|
||||
TIsolated("none", NULL);
|
||||
};
|
||||
|
||||
TIsolated::TIsolated(const string &n, TIsolated *i) :
|
||||
asName( n ), pNext( i )
|
||||
TIsolated::TIsolated(std::string const &n, TIsolated *i) :
|
||||
asName( n ), pNext( i )
|
||||
{
|
||||
// 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
|
||||
TIsolated *p = pRoot;
|
||||
while (p)
|
||||
@@ -121,13 +121,8 @@ void TIsolated::Modify(int i, TDynamicObject *o)
|
||||
if (Global::iMultiplayer) // jeśli multiplayer
|
||||
Global::pGround->WyslijString(asName, 10); // wysłanie pakietu o zwolnieniu
|
||||
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,
|
||||
update_memval2 ); //"zerujemy" ostatnią wartość
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -140,12 +135,7 @@ void TIsolated::Modify(int i, TDynamicObject *o)
|
||||
if (Global::iMultiplayer) // jeśli multiplayer
|
||||
Global::pGround->WyslijString(asName, 11); // wysłanie pakietu o zajęciu
|
||||
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ą
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -154,9 +144,6 @@ void TIsolated::Modify(int i, TDynamicObject *o)
|
||||
TTrack::TTrack(TGroundNode *g) :
|
||||
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[ 1 ] = 0.0;
|
||||
nFouling[ 0 ] = nullptr;
|
||||
@@ -199,7 +186,7 @@ void TTrack::Init()
|
||||
break;
|
||||
case tt_Table: // oba potrzebne
|
||||
SwitchExtension = std::make_shared<TSwitchExtension>( this, 1 ); // kopia oryginalnego toru
|
||||
Segment = make_shared<TSegment>(this);
|
||||
Segment = std::make_shared<TSegment>(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -413,7 +400,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
|
||||
{ // pobranie obiektu trajektorii ruchu
|
||||
vector3 pt, vec, p1, p2, cp1, cp2, p3, p4, cp3, cp4; // dodatkowe punkty potrzebne do skrzyżowań
|
||||
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
|
||||
std::string token;
|
||||
|
||||
@@ -554,8 +541,10 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
|
||||
p2.y += 0.18;
|
||||
// na przechyłce doliczyć jeszcze pół przechyłki
|
||||
}
|
||||
if (fRadius != 0) // gdy podany promień
|
||||
segsize = Min0R(5.0, 0.2 + fabs(fRadius) * 0.02); // do 250m - 5, potem 1 co 50m
|
||||
if( fRadius != 0 ) // gdy podany promień
|
||||
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) ||
|
||||
(((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)) &&
|
||||
(cp2 == vector3(0, 0, 0))) // Ra: hm, czasem dla prostego są podane...
|
||||
Segment->Init(p1, p2, segsize, r1,
|
||||
r2); // gdy prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||
Segment->Init(p1, p2, segsize, r1, r2); // gdy prosty, kontrolne wyliczane przy zmiennej przechyłce
|
||||
else
|
||||
Segment->Init(p1, cp1 + p1, cp2 + p2, p2, segsize, r1,
|
||||
r2); // gdy łuk (ustawia bCurve=true)
|
||||
Segment->Init(p1, cp1 + p1, cp2 + p2, p2, segsize, r1, r2); // gdy łuk (ustawia bCurve=true)
|
||||
if ((r1 != 0) || (r2 != 0))
|
||||
iTrapezoid = 1; // są przechyłki do uwzględniania w rysowaniu
|
||||
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
|
||||
if (!pIsolated)
|
||||
if ((i = name.find("@")) != string::npos)
|
||||
if ((i = name.find("@")) != std::string::npos)
|
||||
if (i < name.length()) // nie może być puste
|
||||
{
|
||||
pIsolated = TIsolated::Find(name.substr(i + 1, name.length()));
|
||||
@@ -976,7 +963,7 @@ bool TTrack::AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus)
|
||||
return false;
|
||||
};
|
||||
|
||||
string TTrack::IsolatedName()
|
||||
std::string TTrack::IsolatedName()
|
||||
{ // podaje nazwę odcinka izolowanego, jesli nie ma on jeszcze przypisanych zdarzeń
|
||||
if (pIsolated)
|
||||
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...
|
||||
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 ) {
|
||||
// jeśli multiplayer
|
||||
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
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
};
|
||||
|
||||
void TTrack::MoveMe(vector3 pPosition)
|
||||
@@ -1863,42 +1828,16 @@ void TTrack::Render()
|
||||
|
||||
bool TTrack::CheckDynamicObject(TDynamicObject *Dynamic)
|
||||
{ // 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 ) {
|
||||
if( dynamic == Dynamic ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic)
|
||||
{ // 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;
|
||||
if( *Dynamics.begin() == Dynamic ) {
|
||||
// most likely the object getting removed is at the front...
|
||||
@@ -1935,7 +1874,6 @@ bool TTrack::RemoveDynamicObject(TDynamicObject *Dynamic)
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TTrack::InMovement()
|
||||
@@ -2457,8 +2395,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start)
|
||||
}
|
||||
};
|
||||
|
||||
void TTrack::RaRenderVBO(int iPtr)
|
||||
{ // renderowanie z użyciem VBO
|
||||
void TTrack::RaRenderVBO( int iPtr ) { // renderowanie z użyciem VBO
|
||||
// Ra 2014-07: trzeba wymienić GL_TRIANGLE_STRIP na GL_TRIANGLES i renderować trójkąty sektora
|
||||
// dla kolejnych tekstur!
|
||||
EnvironmentSet();
|
||||
@@ -2598,7 +2535,7 @@ void TTrack::EnvironmentSet()
|
||||
#else
|
||||
switch( eEnvironment ) {
|
||||
case e_canyon: {
|
||||
Global::daylight.intensity = 0.5f;
|
||||
Global::daylight.intensity = 0.4f;
|
||||
break;
|
||||
}
|
||||
case e_tunnel: {
|
||||
@@ -2640,14 +2577,6 @@ void TTrack::EnvironmentReset()
|
||||
|
||||
void TTrack::RenderDyn()
|
||||
{ // 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 ) {
|
||||
// sam sprawdza, czy VBO; zmienia kontekst VBO!
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
@@ -2656,19 +2585,10 @@ void TTrack::RenderDyn()
|
||||
GfxRenderer.Render( dynamic );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
void TTrack::RenderDynAlpha()
|
||||
{ // 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 ) {
|
||||
// sam sprawdza, czy VBO; zmienia kontekst VBO!
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
@@ -2677,19 +2597,13 @@ void TTrack::RenderDynAlpha()
|
||||
GfxRenderer.Render_Alpha( dynamic );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
void TTrack::RenderDynSounds()
|
||||
{ // 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 ) {
|
||||
dynamic->RenderSounds();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
bool TTrack::SetConnections(int i)
|
||||
@@ -2923,77 +2837,73 @@ TTrack * TTrack::RaAnimate()
|
||||
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 (TextureID1) // Ra: !!!! tu jest do poprawienia
|
||||
{ // iglice liczone tylko dla zwrotnic
|
||||
vector6 rpts3[24], rpts4[24];
|
||||
double fHTW = 0.5 * fabs(fTrackWidth);
|
||||
double fHTW2 = fHTW; // Ra: na razie niech tak będzie
|
||||
double cos1 = 1.0, sin1 = 0.0, cos2 = 1.0, sin2 = 0.0; // Ra: ...
|
||||
for (int i = 0; i < 12; ++i)
|
||||
{
|
||||
rpts3[i] =
|
||||
vector6((fHTW + iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(fHTW + iglica[i].x) * sin1 + iglica[i].y * cos1, iglica[i].z);
|
||||
rpts3[i + 12] =
|
||||
vector6((fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(fHTW2 + szyna[i].x) * sin2 + iglica[i].y * cos2, szyna[i].z);
|
||||
rpts4[11 - i] = vector6((-fHTW - iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(-fHTW - iglica[i].x) * sin1 + iglica[i].y * cos1,
|
||||
iglica[i].z);
|
||||
rpts4[23 - i] =
|
||||
vector6((-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + iglica[i].y * cos2, szyna[i].z);
|
||||
}
|
||||
CVertNormTex Vert[2 * 2 * 12]; // na razie 2 segmenty
|
||||
CVertNormTex *v = Vert; // bo RaAnimate() modyfikuje wskaźnik
|
||||
glGetBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex), &Vert); // pobranie fragmentu bufora VBO
|
||||
if (SwitchExtension->RightSwitch)
|
||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||
SwitchExtension->Segments[0]->RaAnimate(v, rpts3, -nnumPts, fTexLength, 0,
|
||||
2, SwitchExtension->fOffset2);
|
||||
glBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // wysłanie fragmentu bufora VBO
|
||||
v = Vert;
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iRightVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // pobranie fragmentu bufora VBO
|
||||
SwitchExtension->Segments[1]->RaAnimate(v, rpts4, -nnumPts, fTexLength, 0,
|
||||
2, -fMaxOffset +
|
||||
SwitchExtension->fOffset1);
|
||||
}
|
||||
else
|
||||
{ // oryginalnie lewa działała lepiej niż prawa
|
||||
SwitchExtension->Segments[0]->RaAnimate(
|
||||
v, rpts4, -nnumPts, fTexLength, 0, 2,
|
||||
-SwitchExtension->fOffset2); // prawa iglica
|
||||
glBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // wysłanie fragmentu bufora VBO
|
||||
v = Vert;
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iRightVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // pobranie fragmentu bufora VBO
|
||||
SwitchExtension->Segments[1]->RaAnimate(
|
||||
v, rpts3, -nnumPts, fTexLength, 0, 2,
|
||||
fMaxOffset - SwitchExtension->fOffset1); // lewa iglica
|
||||
}
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iRightVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex), &Vert); // wysłanie fragmentu bufora VBO
|
||||
|
||||
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
|
||||
if (TextureID1) // Ra: !!!! tu jest do poprawienia
|
||||
{ // iglice liczone tylko dla zwrotnic
|
||||
vector6 rpts3[24], rpts4[24];
|
||||
double fHTW = 0.5 * fabs(fTrackWidth);
|
||||
double fHTW2 = fHTW; // Ra: na razie niech tak będzie
|
||||
double cos1 = 1.0, sin1 = 0.0, cos2 = 1.0, sin2 = 0.0; // Ra: ...
|
||||
for (int i = 0; i < 12; ++i)
|
||||
{
|
||||
rpts3[i] =
|
||||
vector6((fHTW + iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(fHTW + iglica[i].x) * sin1 + iglica[i].y * cos1, iglica[i].z);
|
||||
rpts3[i + 12] =
|
||||
vector6((fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(fHTW2 + szyna[i].x) * sin2 + iglica[i].y * cos2, szyna[i].z);
|
||||
rpts4[11 - i] = vector6((-fHTW - iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(-fHTW - iglica[i].x) * sin1 + iglica[i].y * cos1,
|
||||
iglica[i].z);
|
||||
rpts4[23 - i] =
|
||||
vector6((-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + iglica[i].y * cos2, szyna[i].z);
|
||||
}
|
||||
}
|
||||
else // gdy Display List
|
||||
Release(); // niszczenie skompilowanej listy, aby się wygenerowała nowa
|
||||
CVertNormTex Vert[2 * 2 * 12]; // na razie 2 segmenty
|
||||
CVertNormTex *v = Vert; // bo RaAnimate() modyfikuje wskaźnik
|
||||
glGetBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex), &Vert); // pobranie fragmentu bufora VBO
|
||||
if (SwitchExtension->RightSwitch)
|
||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||
SwitchExtension->Segments[0]->RaAnimate(v, rpts3, -nnumPts, fTexLength, 0,
|
||||
2, SwitchExtension->fOffset2);
|
||||
glBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // wysłanie fragmentu bufora VBO
|
||||
v = Vert;
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iRightVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // pobranie fragmentu bufora VBO
|
||||
SwitchExtension->Segments[1]->RaAnimate(v, rpts4, -nnumPts, fTexLength, 0,
|
||||
2, -fMaxOffset +
|
||||
SwitchExtension->fOffset1);
|
||||
}
|
||||
else
|
||||
{ // oryginalnie lewa działała lepiej niż prawa
|
||||
SwitchExtension->Segments[0]->RaAnimate(
|
||||
v, rpts4, -nnumPts, fTexLength, 0, 2,
|
||||
-SwitchExtension->fOffset2); // prawa iglica
|
||||
glBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // wysłanie fragmentu bufora VBO
|
||||
v = Vert;
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iRightVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex),
|
||||
&Vert); // pobranie fragmentu bufora VBO
|
||||
SwitchExtension->Segments[1]->RaAnimate(
|
||||
v, rpts3, -nnumPts, fTexLength, 0, 2,
|
||||
fMaxOffset - SwitchExtension->fOffset1); // lewa iglica
|
||||
}
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iRightVBO * sizeof(CVertNormTex),
|
||||
2 * 2 * 12 * sizeof(CVertNormTex), &Vert); // wysłanie fragmentu bufora VBO
|
||||
}
|
||||
}
|
||||
else if (eType == tt_Table) // dla obrotnicy - szyny i podsypka
|
||||
{
|
||||
@@ -3023,36 +2933,27 @@ TTrack * TTrack::RaAnimate()
|
||||
SwitchExtension->vTrans; // SwitchExtension->Segments[0]->FastGetPoint(0.5);
|
||||
Segment->Init(middle + vector3(sina, 0.0, cosa),
|
||||
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 ) {
|
||||
// minimalny ruch, aby przeliczyć pozycję
|
||||
dynamic->Move( 0.000001 );
|
||||
}
|
||||
#endif
|
||||
// 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
|
||||
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
|
||||
{
|
||||
int size =
|
||||
RaArrayPrepare(); // wielkość tabeli potrzebna dla tej obrotnicy
|
||||
CVertNormTex *Vert = new CVertNormTex[size]; // bufor roboczy
|
||||
// CVertNormTex *v=Vert; //zmieniane przez
|
||||
RaArrayFill(Vert,
|
||||
Vert -
|
||||
SwitchExtension
|
||||
->iLeftVBO); // iLeftVBO powinno zostać niezmienione
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
size * sizeof(CVertNormTex), Vert); // wysłanie fragmentu bufora VBO
|
||||
}
|
||||
|
||||
// aktualizacja pojazdów na torze
|
||||
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
|
||||
{
|
||||
int size =
|
||||
RaArrayPrepare(); // wielkość tabeli potrzebna dla tej obrotnicy
|
||||
CVertNormTex *Vert = new CVertNormTex[size]; // bufor roboczy
|
||||
// CVertNormTex *v=Vert; //zmieniane przez
|
||||
RaArrayFill(Vert,
|
||||
Vert -
|
||||
SwitchExtension
|
||||
->iLeftVBO); // iLeftVBO powinno zostać niezmienione
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
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
|
||||
}
|
||||
else
|
||||
@@ -3063,15 +2964,9 @@ TTrack * TTrack::RaAnimate()
|
||||
//---------------------------------------------------------------------------
|
||||
void TTrack::RadioStop()
|
||||
{ // 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 ) {
|
||||
dynamic->RadioStop();
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
double TTrack::WidthTotal()
|
||||
@@ -3180,7 +3075,7 @@ void TTrack::MovedUp1(double dh)
|
||||
fTexHeight1 += dh;
|
||||
};
|
||||
|
||||
string TTrack::NameGet()
|
||||
std::string TTrack::NameGet()
|
||||
{ // ustalenie nazwy toru
|
||||
if (this)
|
||||
if (pMyNode)
|
||||
|
||||
13
Track.h
13
Track.h
@@ -95,10 +95,6 @@ class TSwitchExtension
|
||||
private:
|
||||
};
|
||||
|
||||
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
|
||||
const int iMaxNumDynamics = 40; // McZapkie-100303
|
||||
#endif
|
||||
|
||||
class TIsolated
|
||||
{ // obiekt zbierający zajętości z kilku odcinków
|
||||
int iAxles = 0; // ilość osi na odcinkach obsługiwanych przez obiekt
|
||||
@@ -152,13 +148,8 @@ class TTrack : public Resource
|
||||
TGroundNode *
|
||||
pMyNode = nullptr; // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
|
||||
public:
|
||||
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
|
||||
int iNumDynamics = 0;
|
||||
TDynamicObject *Dynamics[iMaxNumDynamics];
|
||||
#else
|
||||
typedef std::deque<TDynamicObject *> dynamics_sequence;
|
||||
dynamics_sequence Dynamics;
|
||||
#endif
|
||||
int iEvents = 0; // Ra: flaga informująca o obecności eventów
|
||||
TEvent *evEventall0 = nullptr; // McZapkie-140302: wyzwalany gdy pojazd stoi
|
||||
TEvent *evEventall1 = nullptr;
|
||||
@@ -204,11 +195,7 @@ class TTrack : public Resource
|
||||
TTrack * NullCreate(int dir);
|
||||
inline bool IsEmpty()
|
||||
{
|
||||
#ifdef EU07_USE_OLD_TTRACK_DYNAMICS_ARRAY
|
||||
return (iNumDynamics <= 0);
|
||||
#else
|
||||
return Dynamics.empty();
|
||||
#endif
|
||||
};
|
||||
void ConnectPrevPrev(TTrack *pNewPrev, int typ);
|
||||
void ConnectPrevNext(TTrack *pNewPrev, int typ);
|
||||
|
||||
129
Traction.cpp
129
Traction.cpp
@@ -105,139 +105,12 @@ TTraction::TTraction()
|
||||
|
||||
TTraction::~TTraction()
|
||||
{
|
||||
if (!Global::bUseVBO)
|
||||
glDeleteLists(uiDisplayList, 1);
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
14
Train.cpp
14
Train.cpp
@@ -391,9 +391,9 @@ PyObject *TTrain::GetTrainState() {
|
||||
PyDict_SetItemString( dict, "actualproximitydist", PyGetFloat( driver->ActualProximityDist ) );
|
||||
PyDict_SetItemString( dict, "trainnumber", PyGetString( driver->TrainName().c_str() ) );
|
||||
// world state data
|
||||
PyDict_SetItemString( dict, "hours", PyGetInt( GlobalTime->hh ) );
|
||||
PyDict_SetItemString( dict, "minutes", PyGetInt( GlobalTime->mm ) );
|
||||
PyDict_SetItemString( dict, "seconds", PyGetInt( GlobalTime->mr ) );
|
||||
PyDict_SetItemString( dict, "hours", PyGetInt( Simulation::Time.data().wHour ) );
|
||||
PyDict_SetItemString( dict, "minutes", PyGetInt( Simulation::Time.data().wMinute ) );
|
||||
PyDict_SetItemString( dict, "seconds", PyGetInt( Simulation::Time.second() ) );
|
||||
|
||||
return dict;
|
||||
}
|
||||
@@ -2659,7 +2659,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
fTachoVelocity = Min0R(fabs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot),
|
||||
mvControlled->Vmax * 1.05);
|
||||
{ // 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
|
||||
if (ff != fTachoTimer) // jesli w tej sekundzie nie zmienial
|
||||
{
|
||||
@@ -3337,11 +3337,11 @@ bool TTrain::Update( double const Deltatime )
|
||||
// McZapkie-300302: zegarek
|
||||
if (ggClockMInd.SubModel)
|
||||
{
|
||||
ggClockSInd.UpdateValue(int(GlobalTime->mr));
|
||||
ggClockSInd.UpdateValue(Simulation::Time.data().wSecond);
|
||||
ggClockSInd.Update();
|
||||
ggClockMInd.UpdateValue(GlobalTime->mm);
|
||||
ggClockMInd.UpdateValue(Simulation::Time.data().wMinute);
|
||||
ggClockMInd.Update();
|
||||
ggClockHInd.UpdateValue(GlobalTime->hh + GlobalTime->mm / 60.0);
|
||||
ggClockHInd.UpdateValue(Simulation::Time.data().wHour + Simulation::Time.data().wMinute / 60.0);
|
||||
ggClockHInd.Update();
|
||||
}
|
||||
|
||||
|
||||
575
World.cpp
575
World.cpp
@@ -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> UITranscripts = std::make_shared<ui_panel>( 85, 600 ); // voice transcripts
|
||||
|
||||
namespace Simulation {
|
||||
|
||||
simulation_time Time;
|
||||
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
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()
|
||||
{
|
||||
// randomize();
|
||||
@@ -58,9 +195,6 @@ TWorld::TWorld()
|
||||
KeyEvents[i] = NULL; // eventy wyzwalane klawiszami cyfrowymi
|
||||
Global::iSlowMotion = 0;
|
||||
// Global::changeDynObj=NULL;
|
||||
OutText1 = ""; // teksty wyświetlane na ekranie
|
||||
OutText2 = "";
|
||||
OutText3 = "";
|
||||
pDynamicNearest = NULL;
|
||||
fTimeBuffer = 0.0; // bufor czasu aktualizacji dla stałego kroku 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ń
|
||||
|
||||
WriteLog("\nStarting MaSzyna rail vehicle simulator.");
|
||||
WriteLog(Global::asVersion);
|
||||
WriteLog("Online documentation and additional files on http://eu07.pl");
|
||||
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");
|
||||
@@ -180,6 +313,8 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
|
||||
glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii
|
||||
|
||||
Simulation::Time.init();
|
||||
|
||||
Environment.init();
|
||||
Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]);
|
||||
|
||||
@@ -270,14 +405,55 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
};
|
||||
|
||||
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
|
||||
// przełączników [Shift] i [Ctrl]
|
||||
// na każdy kod wirtualny niech przypadają 4 bajty: 2 dla naciśnięcia i 2 dla zwolnienia
|
||||
// powtórzone 256 razy da 1kB na każdy stan przełączników, łącznie będzie 4kB pierwszej tabeli
|
||||
// przekodowania
|
||||
//m7todo: printowanie klawiszy?
|
||||
if (cKey >= '0' && cKey <= '9')
|
||||
{
|
||||
// dump keypress info in the log
|
||||
if( !Global::iPause ) {
|
||||
// podczas pauzy klawisze nie działają
|
||||
std::string keyinfo;
|
||||
auto keyname = glfwGetKeyName( cKey, 0 );
|
||||
if( keyname != nullptr ) {
|
||||
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
|
||||
if (Global::shiftState)
|
||||
@@ -330,11 +506,11 @@ void TWorld::OnKeyDown(int cKey)
|
||||
// additional time speedup keys in debug mode
|
||||
if (Global::ctrlState) {
|
||||
// ctrl-f3
|
||||
GlobalTime->UpdateMTableTime( 20.0 * 60.0 );
|
||||
Simulation::Time.update( 20.0 * 60.0 );
|
||||
}
|
||||
else if (Global::shiftState) {
|
||||
// shift-f3
|
||||
GlobalTime->UpdateMTableTime( 5.0 * 60.0 );
|
||||
Simulation::Time.update( 5.0 * 60.0 );
|
||||
}
|
||||
}
|
||||
if( (!Global::ctrlState)
|
||||
@@ -774,20 +950,19 @@ bool TWorld::Update()
|
||||
if( (Global::iPause == false)
|
||||
|| (m_init == false) )
|
||||
{ // 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)
|
||||
Global::fTimeAngleDeg =
|
||||
GlobalTime->hh * 15.0 + GlobalTime->mm * 0.25 + GlobalTime->mr / 240.0;
|
||||
Global::fClockAngleDeg[0] = 36.0 * (int(GlobalTime->mr) % 10); // jednostki sekund
|
||||
Global::fClockAngleDeg[1] = 36.0 * (int(GlobalTime->mr) / 10); // dziesiątki sekund
|
||||
Global::fClockAngleDeg[2] = 36.0 * (GlobalTime->mm % 10); // jednostki minut
|
||||
Global::fClockAngleDeg[3] = 36.0 * (GlobalTime->mm / 10); // dziesiątki minut
|
||||
Global::fClockAngleDeg[4] = 36.0 * (GlobalTime->hh % 10); // jednostki godzin
|
||||
Global::fClockAngleDeg[5] = 36.0 * (GlobalTime->hh / 10); // dziesiątki godzin
|
||||
Simulation::Time.update( Timer::GetDeltaTime() );
|
||||
auto const &time = Simulation::Time.data();
|
||||
Global::fTimeAngleDeg = time.wHour * 15.0 + time.wMinute * 0.25 + ( ( time.wSecond + 0.001 * time.wMilliseconds ) / 240.0 );
|
||||
Global::fClockAngleDeg[ 0 ] = 36.0 * ( time.wSecond % 10 ); // jednostki sekund
|
||||
Global::fClockAngleDeg[ 1 ] = 36.0 * ( time.wSecond / 10 ); // dziesiątki sekund
|
||||
Global::fClockAngleDeg[ 2 ] = 36.0 * ( time.wMinute % 10 ); // jednostki minut
|
||||
Global::fClockAngleDeg[ 3 ] = 36.0 * ( time.wMinute / 10 ); // dziesiątki minut
|
||||
Global::fClockAngleDeg[ 4 ] = 36.0 * ( time.wHour % 10 ); // jednostki godzin
|
||||
Global::fClockAngleDeg[ 5 ] = 36.0 * ( time.wHour / 10 ); // dziesiątki godzin
|
||||
|
||||
Update_Environment();
|
||||
} // koniec działań niewykonywanych podczas pauzy
|
||||
// poprzednie jakoś tam działało
|
||||
|
||||
// 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
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
|
||||
if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) &&
|
||||
@@ -1407,21 +1581,21 @@ TWorld::Render_Cab() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
if( Global::bUseVBO ) {
|
||||
// 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->RaRenderAlpha( 0.0, dynamic->Material()->replacable_skins, dynamic->Material()->textures_alpha );
|
||||
}
|
||||
else {
|
||||
// renderowanie z Display List
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
// renderowanie z Display List
|
||||
dynamic->mdKabina->Render( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
|
||||
dynamic->mdKabina->RenderAlpha( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
|
||||
#else
|
||||
GfxRenderer.Render( dynamic->mdKabina, dynamic->Material(), 0.0 );
|
||||
GfxRenderer.Render_Alpha( dynamic->mdKabina, dynamic->Material(), 0.0 );
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
GfxRenderer.Render( dynamic->mdKabina, dynamic->Material(), 0.0 );
|
||||
GfxRenderer.Render_Alpha( dynamic->mdKabina, dynamic->Material(), 0.0 );
|
||||
#endif
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
// przywrócenie standardowych, bo zawsze są zmieniane
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight );
|
||||
@@ -1445,20 +1619,21 @@ TWorld::Render_Cab() {
|
||||
void
|
||||
TWorld::Update_UI() {
|
||||
|
||||
OutText1 = OutText2 = OutText3 = OutText4 = "";
|
||||
UITable->text_lines.clear();
|
||||
std::string uitextline1, uitextline2, uitextline3, uitextline4;
|
||||
|
||||
switch( Global::iTextMode ) {
|
||||
|
||||
case( GLFW_KEY_F1 ) : {
|
||||
// f1, default mode: current time and timetable excerpt
|
||||
OutText1 =
|
||||
auto const &time = Simulation::Time.data();
|
||||
uitextline1 =
|
||||
"Time: "
|
||||
+ to_string( (int)GlobalTime->hh ) + ":"
|
||||
+ ( GlobalTime->mm < 10 ? "0" : "" ) + to_string( GlobalTime->mm ) + ":"
|
||||
+ ( GlobalTime->mr < 10 ? "0" : "" ) + to_string( std::floor( GlobalTime->mr ) );
|
||||
+ to_string( time.wHour ) + ":"
|
||||
+ ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
|
||||
+ ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
|
||||
if( Global::iPause ) {
|
||||
OutText1 += " (paused)";
|
||||
uitextline1 += " (paused)";
|
||||
}
|
||||
|
||||
if( Controlled && ( Controlled->Mechanik != nullptr ) ) {
|
||||
@@ -1466,21 +1641,21 @@ TWorld::Update_UI() {
|
||||
auto const &mover = Controlled->MoverParameters;
|
||||
auto const &driver = Controlled->Mechanik;
|
||||
|
||||
OutText2 = "Throttle: " + to_string( driver->Controlling()->MainCtrlPos, 0, 2 ) + "+" + std::to_string( driver->Controlling()->ScndCtrlPos );
|
||||
if( mover->ActiveDir > 0 ) { OutText2 += " D"; }
|
||||
else if( mover->ActiveDir < 0 ) { OutText2 += " R"; }
|
||||
else { OutText2 += " N"; }
|
||||
uitextline2 = "Throttle: " + to_string( driver->Controlling()->MainCtrlPos, 0, 2 ) + "+" + std::to_string( driver->Controlling()->ScndCtrlPos );
|
||||
if( mover->ActiveDir > 0 ) { uitextline2 += " D"; }
|
||||
else if( mover->ActiveDir < 0 ) { uitextline2 += " R"; }
|
||||
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 ) {
|
||||
// detail mode on second key press
|
||||
OutText2 +=
|
||||
uitextline2 +=
|
||||
" 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"
|
||||
+ ", 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)";
|
||||
OutText3 +=
|
||||
uitextline3 +=
|
||||
" Pressure: " + to_string( mover->BrakePress * 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();
|
||||
if( table == nullptr ) { break; }
|
||||
|
||||
OutText1 =
|
||||
auto const &time = Simulation::Time.data();
|
||||
uitextline1 =
|
||||
"Time: "
|
||||
+ to_string( (int)GlobalTime->hh ) + ":"
|
||||
+ ( GlobalTime->mm < 10 ? "0" : "" ) + to_string( GlobalTime->mm ) + ":"
|
||||
+ ( GlobalTime->mr < 10 ? "0" : "" ) + to_string( std::floor( GlobalTime->mr ) );
|
||||
+ to_string( time.wHour ) + ":"
|
||||
+ ( time.wMinute < 10 ? "0" : "" ) + to_string( time.wMinute ) + ":"
|
||||
+ ( time.wSecond < 10 ? "0" : "" ) + to_string( time.wSecond );
|
||||
if( Global::iPause ) {
|
||||
OutText1 += " (paused)";
|
||||
uitextline1 += " (paused)";
|
||||
}
|
||||
|
||||
if( Controlled
|
||||
&& Controlled->Mechanik ) {
|
||||
OutText2 = Global::Bezogonkow( Controlled->Mechanik->Relation(), true ) + " (" + tmp->Mechanik->Timetable()->TrainName + ")";
|
||||
if( !OutText2.empty() ) {
|
||||
uitextline2 = Global::Bezogonkow( Controlled->Mechanik->Relation(), true ) + " (" + tmp->Mechanik->Timetable()->TrainName + ")";
|
||||
if( !uitextline2.empty() ) {
|
||||
// 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 ) {
|
||||
//
|
||||
// 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 ) ) {
|
||||
// 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
|
||||
OutText1 +=
|
||||
uitextline1 +=
|
||||
" C0:" +
|
||||
( tmp->PrevConnected ?
|
||||
tmp->PrevConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 0 ].CouplingFlag ) :
|
||||
"none" );
|
||||
OutText1 +=
|
||||
uitextline1 +=
|
||||
" C1:" +
|
||||
( tmp->NextConnected ?
|
||||
tmp->NextConnected->GetName() + ":" + to_string( tmp->MoverParameters->Couplers[ 1 ].CouplingFlag ) :
|
||||
"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 )
|
||||
OutText2 += "G";
|
||||
uitextline2 += "G";
|
||||
if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_P ) == bdelay_P )
|
||||
OutText2 += "P";
|
||||
uitextline2 += "P";
|
||||
if( ( tmp->MoverParameters->BrakeDelayFlag & bdelay_R ) == bdelay_R )
|
||||
OutText2 += "R";
|
||||
uitextline2 += "R";
|
||||
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. "
|
||||
+ to_string( tmp->MoverParameters->PantPress, 2 )
|
||||
+ ( tmp->MoverParameters->bPantKurek3 ? "<ZG" : "|ZG" );
|
||||
}
|
||||
|
||||
OutText2 +=
|
||||
uitextline2 +=
|
||||
", MED:"
|
||||
+ to_string( tmp->MoverParameters->LocalBrakePosA, 2 )
|
||||
+ "+"
|
||||
+ to_string( tmp->MoverParameters->AnPos, 2 );
|
||||
|
||||
OutText2 +=
|
||||
uitextline2 +=
|
||||
", Ft:"
|
||||
+ to_string( tmp->MoverParameters->Ft * 0.001f, 0 );
|
||||
|
||||
OutText2 +=
|
||||
uitextline2 +=
|
||||
"; TC:"
|
||||
+ to_string( tmp->MoverParameters->TotalCurrent, 0 );
|
||||
OutText2 +=
|
||||
uitextline2 +=
|
||||
", HV0:"
|
||||
+ to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 1 ], 0 )
|
||||
+ "@"
|
||||
+ to_string( tmp->MoverParameters->HVCouplers[ 0 ][ 0 ], 0 );
|
||||
OutText2 +=
|
||||
uitextline2 +=
|
||||
", HV1:"
|
||||
+ to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 1 ], 0 )
|
||||
+ "@"
|
||||
+ to_string( tmp->MoverParameters->HVCouplers[ 1 ][ 0 ], 0 );
|
||||
|
||||
OutText3 =
|
||||
uitextline3 =
|
||||
"BP: " + to_string( tmp->MoverParameters->BrakePress, 2 )
|
||||
+ " (" + to_string( tmp->MoverParameters->BrakeStatus, 0 )
|
||||
+ "), LBP: " + to_string( tmp->MoverParameters->LocBrakePress, 2 )
|
||||
@@ -1651,16 +1827,16 @@ TWorld::Update_UI() {
|
||||
|
||||
if( tmp->MoverParameters->ManualBrakePos > 0 ) {
|
||||
|
||||
OutText3 += ", manual brake on";
|
||||
uitextline3 += ", manual brake on";
|
||||
}
|
||||
|
||||
if( tmp->MoverParameters->LocalBrakePos > 0 ) {
|
||||
|
||||
OutText3 += ", local brake on";
|
||||
uitextline3 += ", local brake on";
|
||||
}
|
||||
else {
|
||||
|
||||
OutText3 += ", local brake off";
|
||||
uitextline3 += ", local brake off";
|
||||
}
|
||||
|
||||
if( tmp->Mechanik ) {
|
||||
@@ -1670,9 +1846,9 @@ TWorld::Update_UI() {
|
||||
if( tmp->Mechanik->DrivigFlags() & j ) // jak bit ustawiony
|
||||
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 )
|
||||
+ " ad=" + to_string( tmp->Mechanik->AccDesired, 2 )
|
||||
+ " Pd=" + to_string( tmp->Mechanik->ActualProximityDist, 0 )
|
||||
@@ -1684,14 +1860,14 @@ TWorld::Update_UI() {
|
||||
if( ( tmp->Mechanik->VelNext == 0.0 )
|
||||
&& ( tmp->Mechanik->eSignNext ) ) {
|
||||
// jeśli ma zapamiętany event semafora, nazwa eventu semafora
|
||||
OutText4 +=
|
||||
uitextline4 +=
|
||||
" ("
|
||||
+ Global::Bezogonkow( tmp->Mechanik->eSignNext->asName )
|
||||
+ ")";
|
||||
}
|
||||
|
||||
// biezaca komenda dla AI
|
||||
OutText4 += ", command: " + tmp->Mechanik->OrderCurrent();
|
||||
uitextline4 += ", command: " + tmp->Mechanik->OrderCurrent();
|
||||
}
|
||||
|
||||
if( Global::iScreenMode[ Global::iTextMode - GLFW_KEY_F1 ] == 1 ) {
|
||||
@@ -1712,7 +1888,7 @@ TWorld::Update_UI() {
|
||||
}
|
||||
else {
|
||||
// wyświetlenie współrzędnych w scenerii oraz kąta kamery, gdy nie mamy wskaźnika
|
||||
OutText1 =
|
||||
uitextline1 =
|
||||
"Camera position: "
|
||||
+ to_string( Camera.Pos.x, 2 ) + " "
|
||||
+ to_string( Camera.Pos.y, 2 ) + " "
|
||||
@@ -1723,8 +1899,8 @@ TWorld::Update_UI() {
|
||||
+ 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 );
|
||||
// current luminance level
|
||||
OutText2 = "Light level: " + to_string( Global::fLuminance, 3 );
|
||||
if( Global::FakeLight ) { OutText2 += "(*)"; }
|
||||
uitextline2 = "Light level: " + to_string( Global::fLuminance, 3 );
|
||||
if( Global::FakeLight ) { uitextline2 += "(*)"; }
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1732,13 +1908,13 @@ TWorld::Update_UI() {
|
||||
|
||||
case( GLFW_KEY_F8 ) : {
|
||||
|
||||
OutText1 =
|
||||
uitextline1 =
|
||||
"Draw range x " + to_string( Global::fDistanceFactor, 1 )
|
||||
+ "; FPS: " + to_string( Timer::GetFPS(), 2 );
|
||||
if( Global::iSlowMotion ) {
|
||||
OutText1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
|
||||
uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
|
||||
}
|
||||
OutText1 +=
|
||||
uitextline1 +=
|
||||
", sectors: " + to_string( Ground.iRendered )
|
||||
+ "/" + to_string( Global::iSegmentsRendered )
|
||||
+ "; FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 );
|
||||
@@ -1748,18 +1924,12 @@ TWorld::Update_UI() {
|
||||
|
||||
case( GLFW_KEY_F9 ) : {
|
||||
// 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 ) {
|
||||
OutText1 += " (multiplayer mode is active)";
|
||||
uitextline1 += " (multiplayer mode is active)";
|
||||
}
|
||||
|
||||
OutText2 =
|
||||
std::string("Rendering mode: ")
|
||||
+ ( Global::bUseVBO ?
|
||||
"VBO" :
|
||||
"Display Lists" )
|
||||
+ ". "
|
||||
+ GfxRenderer.Info();
|
||||
uitextline2 = GfxRenderer.Info();
|
||||
|
||||
// dump last opengl error, if any
|
||||
GLenum glerror = glGetError();
|
||||
@@ -1767,7 +1937,7 @@ TWorld::Update_UI() {
|
||||
Global::LastGLError = to_string( glerror ) + " (" + Global::Bezogonkow( (char *)gluErrorString( glerror ) ) + ")";
|
||||
}
|
||||
if( false == Global::LastGLError.empty() ) {
|
||||
OutText3 =
|
||||
uitextline3 =
|
||||
"Last openGL error: "
|
||||
+ Global::LastGLError;
|
||||
}
|
||||
@@ -1777,16 +1947,16 @@ TWorld::Update_UI() {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F12 ) : {
|
||||
// opcje włączenia i wyłączenia logowania
|
||||
OutText1 = "[0] Debugmode " + std::string( DebugModeFlag ? "(on)" : "(off)" );
|
||||
OutText2 = "[1] log.txt " + std::string( ( Global::iWriteLogEnabled & 1 ) ? "(on)" : "(off)" );
|
||||
OutText3 = "[2] Console " + std::string( ( Global::iWriteLogEnabled & 2 ) ? "(on)" : "(off)" );
|
||||
uitextline1 = "[0] Debugmode " + std::string( DebugModeFlag ? "(on)" : "(off)" );
|
||||
uitextline2 = "[1] log.txt " + std::string( ( Global::iWriteLogEnabled & 1 ) ? "(on)" : "(off)" );
|
||||
uitextline3 = "[2] Console " + std::string( ( Global::iWriteLogEnabled & 2 ) ? "(on)" : "(off)" );
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1804,7 +1974,7 @@ TWorld::Update_UI() {
|
||||
break;
|
||||
}
|
||||
|
||||
OutText1 =
|
||||
uitextline1 =
|
||||
"vel: " + to_string(tmp->GetVelocity(), 2) + " km/h"
|
||||
+ "; dist: " + to_string(tmp->MoverParameters->DistCounter, 2) + " km"
|
||||
+ "; pos: ("
|
||||
@@ -1813,7 +1983,7 @@ TWorld::Update_UI() {
|
||||
+ to_string( tmp->GetPosition().z, 2 )
|
||||
+ ")";
|
||||
|
||||
OutText2 =
|
||||
uitextline2 =
|
||||
"HamZ=" + to_string( tmp->MoverParameters->fBrakeCtrlPos, 1 )
|
||||
+ "; 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 ) + ")"
|
||||
@@ -1829,14 +1999,14 @@ TWorld::Update_UI() {
|
||||
to_string( tmp->MoverParameters->RunningShape.R, 1 ) )
|
||||
+ " An=" + to_string( tmp->MoverParameters->AccN, 2 ); // przyspieszenie poprzeczne
|
||||
|
||||
if( tprev != int( GlobalTime->mr ) ) {
|
||||
tprev = GlobalTime->mr;
|
||||
if( tprev != Simulation::Time.data().wSecond ) {
|
||||
tprev = Simulation::Time.data().wSecond;
|
||||
Acc = ( tmp->MoverParameters->Vel - VelPrev ) / 3.6;
|
||||
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 )
|
||||
+ "; prz.gl. " + to_string( tmp->MoverParameters->PipePress, 2 )
|
||||
+ "; zb.gl. " + to_string( tmp->MoverParameters->CompressedVolume, 2 )
|
||||
@@ -1845,49 +2015,49 @@ TWorld::Update_UI() {
|
||||
|
||||
// McZapkie: warto wiedziec w jakim stanie sa przelaczniki
|
||||
if( tmp->MoverParameters->ConvOvldFlag )
|
||||
OutText3 += " C! ";
|
||||
uitextline3 += " C! ";
|
||||
else if( tmp->MoverParameters->FuseFlag )
|
||||
OutText3 += " F! ";
|
||||
uitextline3 += " F! ";
|
||||
else if( !tmp->MoverParameters->Mains )
|
||||
OutText3 += " () ";
|
||||
uitextline3 += " () ";
|
||||
else {
|
||||
switch(
|
||||
tmp->MoverParameters->ActiveDir *
|
||||
( tmp->MoverParameters->Imin == tmp->MoverParameters->IminLo ?
|
||||
1 :
|
||||
2 ) ) {
|
||||
case 2: { OutText3 += " >> "; break; }
|
||||
case 1: { OutText3 += " -> "; break; }
|
||||
case 0: { OutText3 += " -- "; break; }
|
||||
case -1: { OutText3 += " <- "; break; }
|
||||
case -2: { OutText3 += " << "; break; }
|
||||
case 2: { uitextline3 += " >> "; break; }
|
||||
case 1: { uitextline3 += " -> "; break; }
|
||||
case 0: { uitextline3 += " -- "; break; }
|
||||
case -1: { uitextline3 += " <- "; break; }
|
||||
case -2: { uitextline3 += " << "; break; }
|
||||
}
|
||||
}
|
||||
// McZapkie: predkosc szlakowa
|
||||
if( tmp->MoverParameters->RunningTrack.Velmax == -1 ) {
|
||||
OutText3 += " Vtrack=Vmax";
|
||||
uitextline3 += " Vtrack=Vmax";
|
||||
}
|
||||
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 )
|
||||
|| ( tmp->MoverParameters->TrainType == dt_EZT ) ) {
|
||||
OutText3 +=
|
||||
uitextline3 +=
|
||||
"; pant. " + to_string( tmp->MoverParameters->PantPress, 2 )
|
||||
+ ( tmp->MoverParameters->bPantKurek3 ? "=" : "^" ) + "ZG";
|
||||
}
|
||||
|
||||
// McZapkie: komenda i jej parametry
|
||||
if( tmp->MoverParameters->CommandIn.Command != ( "" ) ) {
|
||||
OutText4 =
|
||||
uitextline4 =
|
||||
"C:" + tmp->MoverParameters->CommandIn.Command
|
||||
+ " V1=" + to_string( tmp->MoverParameters->CommandIn.Value1, 0 )
|
||||
+ " V2=" + to_string( tmp->MoverParameters->CommandIn.Value2, 0 );
|
||||
}
|
||||
if( ( tmp->Mechanik )
|
||||
&& ( tmp->Mechanik->AIControllFlag == AIdriver ) ) {
|
||||
OutText4 +=
|
||||
uitextline4 +=
|
||||
"AI: Vd=" + to_string( tmp->Mechanik->VelDesired, 0 )
|
||||
+ " ad=" + to_string( tmp->Mechanik->AccDesired, 2 )
|
||||
+ " Pd=" + to_string( tmp->Mechanik->ActualProximityDist, 0 )
|
||||
@@ -1927,7 +2097,7 @@ TWorld::Update_UI() {
|
||||
#ifdef EU07_USE_OLD_UI_CODE
|
||||
if( Controlled && DebugModeFlag && !Global::iTextMode ) {
|
||||
|
||||
OutText1 +=
|
||||
uitextline1 +=
|
||||
( "; d_omega " ) + to_string( Controlled->MoverParameters->dizel_engagedeltaomega, 3 );
|
||||
|
||||
if( Controlled->MoverParameters->EngineType == ElectricInductionMotor ) {
|
||||
@@ -1935,7 +2105,7 @@ TWorld::Update_UI() {
|
||||
for( int i = 0; i <= 8; i++ ) {
|
||||
for( int j = 0; j <= 9; 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,24 +2114,23 @@ TWorld::Update_UI() {
|
||||
|
||||
// update the ui header texts
|
||||
auto &headerdata = UIHeader->text_lines;
|
||||
headerdata[ 0 ].data = OutText1;
|
||||
headerdata[ 1 ].data = OutText2;
|
||||
headerdata[ 2 ].data = OutText3;
|
||||
headerdata[ 3 ].data = OutText4;
|
||||
headerdata[ 0 ].data = uitextline1;
|
||||
headerdata[ 1 ].data = uitextline2;
|
||||
headerdata[ 2 ].data = uitextline3;
|
||||
headerdata[ 3 ].data = uitextline4;
|
||||
|
||||
{ // stenogramy dźwięków (ukryć, gdy tabelka skanowania lub rozkład?)
|
||||
auto &transcripts = UITranscripts->text_lines;
|
||||
transcripts.clear();
|
||||
for( auto const &transcript : Global::tranTexts.aLines ) {
|
||||
// stenogramy dźwięków (ukryć, gdy tabelka skanowania lub rozkład?)
|
||||
auto &transcripts = UITranscripts->text_lines;
|
||||
transcripts.clear();
|
||||
for( auto const &transcript : Global::tranTexts.aLines ) {
|
||||
|
||||
if( Global::fTimeAngleDeg >= transcript.fShow ) {
|
||||
if( Global::fTimeAngleDeg >= transcript.fShow ) {
|
||||
|
||||
cParser parser( transcript.asText );
|
||||
while( true == parser.getTokens(1, false, "|") ) {
|
||||
cParser parser( transcript.asText );
|
||||
while( true == parser.getTokens( 1, false, "|" ) ) {
|
||||
|
||||
std::string transcriptline; parser >> transcriptline;
|
||||
transcripts.emplace_back( transcriptline, float4( 1.0f, 1.0f, 0.0f, 1.0f ) );
|
||||
}
|
||||
std::string transcriptline; parser >> transcriptline;
|
||||
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
|
||||
{
|
||||
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)
|
||||
Global::fMoveLight = t; // trzeba by deklinację Słońca przeliczyć
|
||||
GlobalTime->hh = floor(24 * t) - 24.0 * GlobalTime->dd;
|
||||
GlobalTime->mm =
|
||||
floor(60 * 24 * t) - 60.0 * (24.0 * GlobalTime->dd + GlobalTime->hh);
|
||||
GlobalTime->mr =
|
||||
floor(60 * 60 * 24 * t) -
|
||||
60.0 * (60.0 * (24.0 * GlobalTime->dd + GlobalTime->hh) + GlobalTime->mm);
|
||||
Simulation::Time.data().wHour = std::floor(24 * t) - 24.0 * Simulation::Time.data().wDay;
|
||||
Simulation::Time.data().wMinute = std::floor(60 * 24 * t) - 60.0 * (24.0 * Simulation::Time.data().wDay + Simulation::Time.data().wHour);
|
||||
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 );
|
||||
}
|
||||
if (*pRozkaz->iPar & 2)
|
||||
{ // ustawienie flag zapauzowania
|
||||
@@ -2333,79 +2499,88 @@ world_environment::init() {
|
||||
|
||||
m_skydome.init();
|
||||
m_sun.init();
|
||||
m_moon.init();
|
||||
m_stars.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;
|
||||
|
||||
void
|
||||
world_environment::render() {
|
||||
world_environment::update() {
|
||||
// move celestial bodies...
|
||||
m_sun.update();
|
||||
m_moon.update();
|
||||
// ...determine source of key light and adjust global state accordingly...
|
||||
auto const sunlightlevel = m_sun.getIntensity();
|
||||
auto const moonlightlevel = m_moon.getIntensity();
|
||||
float keylightintensity;
|
||||
float twilightfactor;
|
||||
float3 keylightcolor;
|
||||
if (moonlightlevel > sunlightlevel) {
|
||||
// rare situations when the moon is brighter than the sun, typically at night
|
||||
Global::SunAngle = m_moon.getAngle();
|
||||
Math3D::vector3 moon_dir = -1.0 * m_moon.getDirection();
|
||||
Global::daylight.direction = glm::vec3(moon_dir.x, moon_dir.y, moon_dir.z);
|
||||
keylightintensity = moonlightlevel;
|
||||
// if the moon is up, it overrides the twilight
|
||||
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);
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
// 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
|
||||
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;
|
||||
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_FOG );
|
||||
::glDisable( GL_DEPTH_TEST );
|
||||
::glDepthMask( GL_FALSE );
|
||||
::glPushMatrix();
|
||||
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
|
||||
// tonal impact of skydome color is inversely proportional to how high the sun is above the horizon
|
||||
// (this is pure conjecture, aimed more to 'look right' than be accurate)
|
||||
float const ambienttone = clamp(1.0f - (Global::SunAngle / 90.0f), 0.0f, 1.0f);
|
||||
Global::daylight.ambient.x = interpolate(skydomehsv.z, skydomecolour.x, ambienttone);
|
||||
Global::daylight.ambient.y = interpolate(skydomehsv.z, skydomecolour.y, ambienttone);
|
||||
Global::daylight.ambient.z = interpolate(skydomehsv.z, skydomecolour.z, ambienttone);
|
||||
|
||||
m_skydome.Render();
|
||||
m_stars.render();
|
||||
m_clouds.Render( m_skydome.GetAverageColor() * 2.5f );
|
||||
Global::fLuminance = intensity;
|
||||
|
||||
if( DebugModeFlag == true ) {
|
||||
// mark sun position for easier debugging
|
||||
m_sun.render();
|
||||
}
|
||||
// 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
|
||||
|
||||
World.shader.set_ambient(Global::daylight.ambient);
|
||||
World.shader.set_light(0, gl_program_light::DIR, Global::daylight.position, Global::daylight.direction,
|
||||
0.0f, 0.0f, Global::daylight.color * Global::daylight.intensity, 0.0f, 0.0f);
|
||||
|
||||
::glPopMatrix();
|
||||
::glDepthMask( GL_TRUE );
|
||||
::glEnable( GL_DEPTH_TEST );
|
||||
::glEnable( GL_FOG );
|
||||
::glEnable( GL_LIGHTING );
|
||||
::glClearColor(skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f); // kolor nieba
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
68
World.h
68
World.h
@@ -15,24 +15,65 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Ground.h"
|
||||
#include "sky.h"
|
||||
#include "sun.h"
|
||||
#include "moon.h"
|
||||
#include "stars.h"
|
||||
#include "skydome.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
|
||||
class world_environment {
|
||||
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
void init();
|
||||
void update();
|
||||
void render();
|
||||
void time( int const Hour = -1, int const Minute = -1, int const Second = -1 );
|
||||
|
||||
private:
|
||||
CSkyDome m_skydome;
|
||||
cStars m_stars;
|
||||
cSun m_sun;
|
||||
cMoon m_moon;
|
||||
TSky m_clouds;
|
||||
};
|
||||
|
||||
@@ -45,11 +86,19 @@ class TWorld
|
||||
void FollowView(bool wycisz = true);
|
||||
void DistantView( bool const Near = false );
|
||||
|
||||
public:
|
||||
public:
|
||||
// types
|
||||
|
||||
// constructors
|
||||
TWorld();
|
||||
|
||||
// destructor
|
||||
~TWorld();
|
||||
|
||||
// methods
|
||||
bool Init( GLFWwindow *w );
|
||||
bool InitPerformed() { return m_init; }
|
||||
GLFWwindow *window;
|
||||
GLvoid glPrint(std::string const &Text);
|
||||
void OnKeyDown(int cKey);
|
||||
void OnKeyUp(int cKey);
|
||||
// void UpdateWindow();
|
||||
@@ -59,19 +108,14 @@ class TWorld
|
||||
void TrainDelete(TDynamicObject *d = NULL);
|
||||
// switches between static and dynamic daylight calculation
|
||||
void ToggleDaylight();
|
||||
TWorld();
|
||||
~TWorld();
|
||||
// double Aspect;
|
||||
private:
|
||||
std::string OutText1; // teksty na ekranie
|
||||
std::string OutText2;
|
||||
std::string OutText3;
|
||||
std::string OutText4;
|
||||
|
||||
private:
|
||||
void Update_Environment();
|
||||
void Update_Camera( const double Deltatime );
|
||||
void Update_UI();
|
||||
void ResourceSweep();
|
||||
void Render_Cab();
|
||||
|
||||
TCamera Camera;
|
||||
TGround Ground;
|
||||
world_environment Environment;
|
||||
|
||||
5
dumb3d.h
5
dumb3d.h
@@ -139,14 +139,15 @@ class matrix4x4
|
||||
// the column increasing fastest. However, some APIs (OpenGL in particular) do this
|
||||
// backwards, hence the "constructor" from C matrices, or from OpenGL matrices.
|
||||
// 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;
|
||||
for (int y = 0; y < 4; ++y)
|
||||
for (int x = 0; x < 4; ++x)
|
||||
(*this)(x)[y] = initArray[i++];
|
||||
}
|
||||
void OpenGL_Matrix(scalar_t *initArray)
|
||||
template <typename _Type>
|
||||
void OpenGL_Matrix(_Type const *initArray)
|
||||
{
|
||||
int i = 0;
|
||||
for (int x = 0; x < 4; ++x)
|
||||
|
||||
15
frustum.cpp
15
frustum.cpp
@@ -11,10 +11,19 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "frustum.h"
|
||||
|
||||
void
|
||||
cFrustum::calculate( glm::mat4 &Projection, glm::mat4 &Modelview ) {
|
||||
cFrustum::calculate() {
|
||||
|
||||
float *proj = &Projection[ 0 ][ 0 ];
|
||||
float *modl = &Modelview[ 0 ][ 0 ];
|
||||
auto const &projection = OpenGLMatrices.data( GL_PROJECTION );
|
||||
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 ];
|
||||
|
||||
// multiply the matrices to retrieve clipping planes
|
||||
|
||||
@@ -21,8 +21,10 @@ public:
|
||||
|
||||
// methods:
|
||||
// update the frustum to match current view orientation
|
||||
void
|
||||
calculate();
|
||||
void
|
||||
calculate(glm::mat4 &Projection, glm::mat4 &Modelview);
|
||||
calculate(glm::mat4 const &Projection, glm::mat4 const &Modelview);
|
||||
// returns true if specified point is inside of the frustum
|
||||
inline
|
||||
bool
|
||||
|
||||
@@ -73,16 +73,18 @@ light_array::update() {
|
||||
else {
|
||||
light.intensity = 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
// crude catch for unmanned modules which share the light state with the controlled unit.
|
||||
// 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
|
||||
// NOTE: should be no longer needed, test and delete if there's no ill effects
|
||||
if( ( light.owner->Controller == AIdriver )
|
||||
&& ( light.owner->Mechanik == nullptr ) ) {
|
||||
|
||||
light.intensity = 0.0f;
|
||||
light.count = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// with battery off the lights are off
|
||||
|
||||
325
moon.cpp
Normal file
325
moon.cpp
Normal 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
106
moon.h
Normal 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;
|
||||
};
|
||||
31
mtable.cpp
31
mtable.cpp
@@ -1,7 +1,3 @@
|
||||
/** @file
|
||||
@brief
|
||||
*/
|
||||
|
||||
/*
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
@@ -15,9 +11,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "mtable.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*/
|
||||
// zwraca różnicę czasu
|
||||
// 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
|
||||
}
|
||||
|
||||
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*/
|
||||
{
|
||||
bool OK;
|
||||
@@ -138,13 +136,13 @@ std::string TTrainParameters::ShowRelation()
|
||||
return "";
|
||||
}
|
||||
|
||||
TTrainParameters::TTrainParameters(std::string NewTrainName)
|
||||
TTrainParameters::TTrainParameters(std::string const &NewTrainName)
|
||||
/*wstępne ustawienie parametrów rozkładu jazdy*/
|
||||
{
|
||||
NewName(NewTrainName);
|
||||
}
|
||||
|
||||
void TTrainParameters::NewName(std::string NewTrainName)
|
||||
void TTrainParameters::NewName(std::string const &NewTrainName)
|
||||
/*wstępne ustawienie parametrów rozkładu jazdy*/
|
||||
{
|
||||
TrainName = NewTrainName;
|
||||
@@ -519,30 +517,29 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
||||
void TMTableTime::UpdateMTableTime(double deltaT)
|
||||
// dodanie czasu (deltaT) w sekundach, z przeliczeniem godziny
|
||||
{
|
||||
mr = mr + deltaT; // dodawanie sekund
|
||||
while (mr > 60.0) // przeliczenie sekund do właściwego przedziału
|
||||
mr += deltaT; // dodawanie sekund
|
||||
while (mr >= 60.0) // przeliczenie sekund do właściwego przedziału
|
||||
{
|
||||
mr = mr - 60.0;
|
||||
mr -= 60.0;
|
||||
++mm;
|
||||
}
|
||||
while (mm > 59) // przeliczenie minut do właściwego przedziału
|
||||
{
|
||||
mm = mm - 60;
|
||||
mm -= 60;
|
||||
++hh;
|
||||
}
|
||||
while (hh > 23) // przeliczenie godzin do właściwego przedziału
|
||||
{
|
||||
hh = hh - 24;
|
||||
hh -= 24;
|
||||
++dd; // zwiększenie numeru dnia
|
||||
}
|
||||
GameTime = GameTime + deltaT;
|
||||
}
|
||||
|
||||
bool TTrainParameters::DirectionChange()
|
||||
// sprawdzenie, czy po zatrzymaniu wykonać kolejne komendy
|
||||
{
|
||||
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 false;
|
||||
}
|
||||
|
||||
24
mtable.h
24
mtable.h
@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "world.h"
|
||||
|
||||
namespace Mtable
|
||||
{
|
||||
@@ -73,9 +74,10 @@ class TTrainParameters
|
||||
std::string NextStop();
|
||||
bool IsStop();
|
||||
bool IsTimeToGo(double hh, double mm);
|
||||
bool UpdateMTable(double hh, double mm, std::string NewName);
|
||||
TTrainParameters(std::string NewTrainName);
|
||||
void NewName(std::string NewTrainName);
|
||||
bool UpdateMTable(double hh, double mm, std::string const &NewName);
|
||||
bool UpdateMTable( simulation_time const &Time, std::string const &NewName );
|
||||
TTrainParameters( std::string const &NewTrainName );
|
||||
void NewName(std::string const &NewTrainName);
|
||||
void UpdateVelocity(int StationCount, double vActual);
|
||||
bool LoadTTfile(std::string scnpath, int iPlus, double vmax);
|
||||
bool DirectionChange();
|
||||
@@ -86,29 +88,19 @@ class TMTableTime
|
||||
|
||||
{
|
||||
public:
|
||||
double GameTime = 0.0;
|
||||
int dd = 0;
|
||||
int hh = 0;
|
||||
int mm = 0;
|
||||
int srh = 0;
|
||||
int srm = 0; /*wschod slonca*/
|
||||
int ssh = 0;
|
||||
int ssm = 0; /*zachod slonca*/
|
||||
double mr = 0.0;
|
||||
void UpdateMTableTime(double deltaT);
|
||||
TMTableTime(int InitH, int InitM, int InitSRH, int InitSRM, int InitSSH, int InitSSM) :
|
||||
hh( InitH ),
|
||||
mm( InitM ),
|
||||
srh( InitSRH ),
|
||||
srm( InitSRM ),
|
||||
ssh( InitSSH ),
|
||||
ssm( InitSSM )
|
||||
TMTableTime(int InitH, int InitM ) :
|
||||
hh( InitH ),
|
||||
mm( InitM )
|
||||
{}
|
||||
|
||||
TMTableTime() = default;
|
||||
};
|
||||
|
||||
extern std::shared_ptr<TMTableTime> GlobalTime;
|
||||
}
|
||||
|
||||
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
|
||||
|
||||
13
openglmatrixstack.cpp
Normal file
13
openglmatrixstack.cpp
Normal 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
183
openglmatrixstack.h
Normal 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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
566
renderer.cpp
566
renderer.cpp
@@ -15,6 +15,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "dynobj.h"
|
||||
#include "uilayer.h"
|
||||
#include "logs.h"
|
||||
#include "usefull.h"
|
||||
#include "World.h"
|
||||
|
||||
opengl_renderer GfxRenderer;
|
||||
extern TWorld World;
|
||||
@@ -101,7 +103,13 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
World.shader = gl_program_light({ gl_shader("lighting.vert"), gl_shader("blinnphong.frag") });
|
||||
Global::daylight.intensity = 1.0f; //m7todo: przenieść
|
||||
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -115,29 +123,21 @@ opengl_renderer::Render() {
|
||||
::glDepthFunc( GL_LEQUAL );
|
||||
|
||||
::glMatrixMode( GL_PROJECTION ); // select the Projection Matrix
|
||||
glm::mat4 projection = glm::perspective(
|
||||
Global::FieldOfView / Global::ZoomFactor * 0.0174532925f,
|
||||
::gluPerspective(
|
||||
Global::FieldOfView / Global::ZoomFactor,
|
||||
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
m_drawrange * Global::fDistanceFactor );
|
||||
::glLoadMatrixf( &projection[0][0] );
|
||||
|
||||
::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
|
||||
glm::mat4 modelview( 1.0f );
|
||||
::glLoadIdentity();
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
|
||||
World.Camera.SetMatrix( modelview );
|
||||
::glLoadMatrixf( &modelview[ 0 ][ 0 ] );
|
||||
m_camera.update_frustum( projection, modelview );
|
||||
World.Camera.SetMatrix();
|
||||
m_camera.update_frustum();
|
||||
|
||||
if( !Global::bWireFrame ) {
|
||||
// bez nieba w trybie rysowania linii
|
||||
World.Environment.render();
|
||||
}
|
||||
|
||||
glDebug("rendering ground");
|
||||
Render( &World.Environment );
|
||||
World.Ground.Render( World.Camera.Pos );
|
||||
|
||||
glDebug("rendering cab");
|
||||
@@ -154,12 +154,135 @@ opengl_renderer::Render() {
|
||||
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
|
||||
opengl_renderer::Render( TGround *Ground ) {
|
||||
|
||||
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 );
|
||||
glColor3f( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
@@ -194,6 +317,7 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
|
||||
Dynamic->renderme = true;
|
||||
|
||||
// setup
|
||||
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
|
||||
double squaredistance = SquareMagnitude( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor;
|
||||
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
|
||||
@@ -216,63 +340,34 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
Global::daylight.intensity = Dynamic->fShade;
|
||||
}
|
||||
|
||||
// TODO: implement universal render path down the road
|
||||
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 ) {
|
||||
// render
|
||||
if( Dynamic->mdLowPolyInt ) {
|
||||
// low poly interior
|
||||
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 );
|
||||
}
|
||||
// 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 );
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||
|
||||
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 );
|
||||
}
|
||||
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 ) {
|
||||
// low poly interior
|
||||
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 );
|
||||
}
|
||||
|
||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||
|
||||
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
|
||||
}
|
||||
|
||||
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||
|
||||
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
|
||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance );
|
||||
|
||||
// post-render cleanup
|
||||
if( Dynamic->fShade > 0.0f ) {
|
||||
// restore regular light level
|
||||
Global::daylight.intensity = 1.0f;
|
||||
@@ -301,14 +396,25 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
|
||||
}
|
||||
|
||||
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(
|
||||
( Material != nullptr ?
|
||||
Material->replacable_skins :
|
||||
nullptr ),
|
||||
alpha );
|
||||
|
||||
Model->Root->RenderDL();
|
||||
Model->Root->pRoot = Model;
|
||||
|
||||
// render
|
||||
Render(Model->Root);
|
||||
|
||||
// post-render cleanup
|
||||
Model->EndVBO();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -332,6 +438,154 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
|
||||
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
|
||||
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
|
||||
@@ -339,9 +593,10 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// setup
|
||||
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
|
||||
|
||||
::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
|
||||
|
||||
::glMultMatrixd( Dynamic->mMatrix.getArray() );
|
||||
// wersja Display Lists
|
||||
// NOTE: VBO path is removed
|
||||
// TODO: implement universal render path down the road
|
||||
|
||||
if( Dynamic->fShade > 0.0f ) {
|
||||
// change light level based on light level of the occupied track
|
||||
Global::daylight.intensity = Dynamic->fShade;
|
||||
}
|
||||
|
||||
// render
|
||||
if( Dynamic->mdLowPolyInt ) {
|
||||
// low poly interior
|
||||
if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) {
|
||||
@@ -382,6 +641,12 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
|
||||
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();
|
||||
|
||||
if( Dynamic->btnOn )
|
||||
@@ -405,13 +670,24 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
|
||||
|
||||
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(
|
||||
( Material != nullptr ?
|
||||
Material->replacable_skins :
|
||||
nullptr ),
|
||||
Material->replacable_skins :
|
||||
nullptr ),
|
||||
alpha );
|
||||
|
||||
Model->Root->RenderAlphaDL();
|
||||
Model->Root->pRoot = Model;
|
||||
|
||||
// render
|
||||
Render_Alpha( Model->Root );
|
||||
|
||||
// post-render cleanup
|
||||
Model->EndVBO();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -434,8 +710,129 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
opengl_renderer::Update ( double const Deltatime ) {
|
||||
|
||||
@@ -530,17 +927,20 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
|
||||
// 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
|
||||
float3 position(scenelight.position.x, scenelight.position.y, scenelight.position.z);
|
||||
float3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z);
|
||||
float3 color(scenelight.color.x,
|
||||
scenelight.color.y,
|
||||
scenelight.color.z);
|
||||
glm::vec3 position(scenelight.position.x, scenelight.position.y, scenelight.position.z);
|
||||
glm::vec3 direction(scenelight.direction.x, scenelight.direction.y, scenelight.direction.z);
|
||||
glm::vec3 color(scenelight.color.x,
|
||||
scenelight.color.y,
|
||||
scenelight.color.z);
|
||||
|
||||
World.shader.set_light((GLuint)renderlight + 1, gl_program_light::SPOT, position, direction, 0.906f, 0.866f, color, 0.007f, 0.0002f);
|
||||
|
||||
++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);
|
||||
}
|
||||
|
||||
@@ -560,8 +960,8 @@ opengl_renderer::Init_caps() {
|
||||
+ " Vendor: " + std::string( (char *)glGetString( GL_VENDOR ) )
|
||||
+ " OpenGL Version: " + oglversion );
|
||||
|
||||
if( !GLEW_VERSION_1_4 ) {
|
||||
ErrorLog( "Requires openGL >= 1.4" );
|
||||
if( !GLEW_VERSION_3_2 ) {
|
||||
ErrorLog( "Requires openGL >= 3.2" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
20
renderer.h
20
renderer.h
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "frustum.h"
|
||||
#include "ground.h"
|
||||
#include "shader.h"
|
||||
#include "World.h"
|
||||
|
||||
// encapsulates basic rendering setup.
|
||||
// for modern opengl this translates to a specific collection of glsl shaders,
|
||||
@@ -37,6 +38,9 @@ class opengl_camera {
|
||||
public:
|
||||
// methods:
|
||||
inline
|
||||
void
|
||||
update_frustum() { m_frustum.calculate(); }
|
||||
inline
|
||||
void
|
||||
update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); }
|
||||
bool
|
||||
@@ -61,7 +65,8 @@ public:
|
||||
// main draw call. returns false on error
|
||||
bool
|
||||
Render();
|
||||
#ifndef EU07_USE_OLD_RENDERCODE
|
||||
bool
|
||||
Render( world_environment *Environment );
|
||||
bool
|
||||
Render( TGround *Ground );
|
||||
bool
|
||||
@@ -70,13 +75,18 @@ public:
|
||||
Render( TModel3d *Model, material_data const *Material, double const Squaredistance );
|
||||
bool
|
||||
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
|
||||
Render_Alpha( TDynamicObject *Dynamic );
|
||||
bool
|
||||
Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance );
|
||||
bool
|
||||
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
|
||||
void
|
||||
Update( double const Deltatime);
|
||||
@@ -119,7 +129,8 @@ private:
|
||||
};
|
||||
|
||||
// methods
|
||||
bool Init_caps();
|
||||
bool
|
||||
Init_caps();
|
||||
|
||||
// members
|
||||
rendermode renderpass{ rendermode::color };
|
||||
@@ -130,6 +141,9 @@ private:
|
||||
double m_updateaccumulator{ 0.0 };
|
||||
std::string m_debuginfo;
|
||||
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;
|
||||
|
||||
25
shader.cpp
25
shader.cpp
@@ -103,12 +103,12 @@ void gl_program_mvp::copy_gl_mvp()
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -117,7 +117,6 @@ gl_program_light::gl_program_light(std::vector<gl_shader> v) : gl_program_mvp(v)
|
||||
{
|
||||
ambient_uniform = glGetUniformLocation(id, "ambient");
|
||||
lcount_uniform = glGetUniformLocation(id, "lights_count");
|
||||
specular_uniform = glGetUniformLocation(id, "specular");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void gl_program_light::set_ambient(float3 &ambient)
|
||||
void gl_program_light::set_ambient(glm::vec3 &ambient)
|
||||
{
|
||||
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)
|
||||
@@ -148,13 +147,11 @@ void gl_program_light::set_light_count(GLuint 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,
|
||||
float3 &color, float linear, float quadratic)
|
||||
glm::vec3 &color, float linear, float quadratic)
|
||||
{
|
||||
float arr[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, arr);
|
||||
glm::mat4 mv = glm::make_mat4(arr);
|
||||
glm::mat4 mv = OpenGLMatrices.data(GL_MODELVIEW);
|
||||
|
||||
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);
|
||||
@@ -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));
|
||||
glUniform1f(lights_uniform[i].in_cutoff, in_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].quadratic, quadratic);
|
||||
}
|
||||
|
||||
void gl_program_light::set_object(float specular)
|
||||
{
|
||||
glUseProgram(id);
|
||||
glUniform1f(specular_uniform, specular);
|
||||
}
|
||||
12
shader.h
12
shader.h
@@ -35,8 +35,8 @@ public:
|
||||
gl_program_mvp() = default;
|
||||
gl_program_mvp(std::vector<gl_shader>);
|
||||
|
||||
void set_mv(glm::mat4 &);
|
||||
void set_p(glm::mat4 &);
|
||||
void set_mv(const glm::mat4 &);
|
||||
void set_p(const glm::mat4 &);
|
||||
void copy_gl_mvp();
|
||||
};
|
||||
|
||||
@@ -55,16 +55,14 @@ public:
|
||||
gl_program_light() = default;
|
||||
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(GLuint id, type t, float3 &pos, float3 &dir, float in_cutoff, float out_cutoff,
|
||||
float3 &color, float linear, float quadratic);
|
||||
void set_object(float specular);
|
||||
void set_light(GLuint id, type t, glm::vec3 &pos, glm::vec3 &dir, float in_cutoff, float out_cutoff,
|
||||
glm::vec3 &color, float linear, float quadratic);
|
||||
|
||||
private:
|
||||
GLuint lcount_uniform;
|
||||
GLuint ambient_uniform;
|
||||
GLuint specular_uniform;
|
||||
struct light_s
|
||||
{
|
||||
GLuint type;
|
||||
|
||||
12
sky.cpp
12
sky.cpp
@@ -39,21 +39,21 @@ void TSky::Render( float3 const &Tint )
|
||||
GfxRenderer.Disable_Lights();
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x );
|
||||
#endif
|
||||
if (Global::bUseVBO)
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
if( Global::bUseVBO )
|
||||
{ // renderowanie z VBO
|
||||
mdCloud->RaRender( 100, 0 );
|
||||
mdCloud->RaRenderAlpha(100, 0);
|
||||
}
|
||||
else
|
||||
{ // renderowanie z Display List
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
mdCloud->Render(100, 0);
|
||||
mdCloud->RenderAlpha(100, 0);
|
||||
#else
|
||||
GfxRenderer.Render( mdCloud, nullptr, 100.0 );
|
||||
GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 );
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
GfxRenderer.Render( mdCloud, nullptr, 100.0 );
|
||||
GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 );
|
||||
#endif
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
glPopMatrix();
|
||||
// TODO: re-implement this
|
||||
|
||||
13
skydome.cpp
13
skydome.cpp
@@ -206,7 +206,7 @@ void CSkyDome::SetGammaCorrection( float const Gamma ) {
|
||||
|
||||
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 ) {
|
||||
@@ -299,7 +299,7 @@ void CSkyDome::RebuildColors() {
|
||||
|
||||
// luminance(Y) for clear & overcast sky
|
||||
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 X = (x / y) * Y;
|
||||
@@ -317,6 +317,11 @@ void CSkyDome::RebuildColors() {
|
||||
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
|
||||
// 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 );
|
||||
@@ -340,8 +345,8 @@ void CSkyDome::RebuildColors() {
|
||||
*/
|
||||
// crude correction for the times where the model breaks (late night)
|
||||
// TODO: use proper night sky calculation for these times instead
|
||||
if( ( color.x <= 0.0f )
|
||||
&& ( color.y <= 0.0f ) ) {
|
||||
if( ( color.x <= 0.05f )
|
||||
&& ( color.y <= 0.05f ) ) {
|
||||
// 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'
|
||||
color.z = 0.75f * std::max( color.z + m_sundirection.y, 0.075f );
|
||||
|
||||
@@ -18,11 +18,16 @@ cStars::render() {
|
||||
::glPushMatrix();
|
||||
|
||||
::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 );
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
m_stars.Render( 1.0 );
|
||||
if( Global::bUseVBO ) {
|
||||
m_stars.RaRender( 1.0, 0 );
|
||||
}
|
||||
else {
|
||||
m_stars.Render( 1.0 );
|
||||
}
|
||||
#else
|
||||
GfxRenderer.Render( &m_stars, nullptr, 1.0 );
|
||||
#endif
|
||||
|
||||
1
stdafx.h
1
stdafx.h
@@ -78,6 +78,7 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "openglmatrixstack.h"
|
||||
#define STRINGIZE_DETAIL(x) #x
|
||||
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
|
||||
#define glDebug(x) if (GLEW_GREMEDY_string_marker) glStringMarkerGREMEDY(0, __FILE__ ":" STRINGIZE(__LINE__) ": " x);
|
||||
216
sun.cpp
216
sun.cpp
@@ -4,6 +4,7 @@
|
||||
#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,
|
||||
@@ -32,7 +33,7 @@ void
|
||||
cSun::update() {
|
||||
|
||||
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.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
|
||||
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 );
|
||||
// debug line to locate the sun easier
|
||||
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
|
||||
gluSphere( sunsphere, (float)(m_body.distance * 9.359157), 12, 12 );
|
||||
glPopMatrix();
|
||||
glEnable(GL_FOG);
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
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 ) {
|
||||
|
||||
m_observer.hour = clamp( Hour, -1, 23 );
|
||||
m_observer.minute = clamp( Minute, 0, 59 );
|
||||
m_observer.second = clamp( Second, 0, 59 );
|
||||
m_observer.minute = clamp( Minute, -1, 59 );
|
||||
m_observer.second = clamp( Second, -1, 59 );
|
||||
}
|
||||
|
||||
void cSun::setTemperature( float const Temperature ) {
|
||||
@@ -115,106 +112,109 @@ void cSun::setPressure( float const Pressure ) {
|
||||
|
||||
void cSun::move() {
|
||||
|
||||
static double degrad = 57.295779513; // converts from radians to degrees
|
||||
static double raddeg = 0.0174532925; // converts from degrees to radians
|
||||
static double radtodeg = 57.295779513; // converts from radians to degrees
|
||||
static double degtorad = 0.0174532925; // converts from degrees to radians
|
||||
|
||||
SYSTEMTIME localtime; // time for the calculation
|
||||
time( &localtime );
|
||||
SYSTEMTIME localtime = Simulation::Time.data(); // time for the calculation
|
||||
|
||||
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.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);
|
||||
+ 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
|
||||
// Universal Coordinated (Greenwich standard) time
|
||||
m_observer.utime = ut * 3600.0;
|
||||
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
|
||||
|
||||
// mean longitude
|
||||
m_body.mnlong = 280.460 + 0.9856474 * daynumber;
|
||||
m_body.mnlong -= 360.0 * (int) ( m_body.mnlong / 360.0 ); // clamp the range to 0-360
|
||||
if( m_body.mnlong < 0.0 ) m_body.mnlong += 360.0;
|
||||
|
||||
// mean anomaly
|
||||
m_body.mnanom = 357.528 + 0.9856003 * daynumber;
|
||||
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
|
||||
|
||||
// perihelion longitude
|
||||
m_body.phlong = 282.9404 + 4.70935e-5 * daynumber; // w
|
||||
// orbit eccentricity
|
||||
double const e = 0.016709 - 1.151e-9 * daynumber;
|
||||
// mean anomaly
|
||||
m_body.mnanom = clamp_circular( 356.0470 + 0.9856002585 * daynumber ); // M
|
||||
// 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
|
||||
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 ) );
|
||||
|
||||
// declination
|
||||
m_body.declin = degrad * asin( sin (m_body.ecobli * raddeg) * sin (m_body.eclong * raddeg) );
|
||||
// right ascension
|
||||
double top = std::cos( degtorad * m_body.oblecl ) * std::sin( degtorad * m_body.eclong );
|
||||
double bottom = std::cos( degtorad * m_body.eclong );
|
||||
|
||||
// right ascension
|
||||
double top = cos ( raddeg * m_body.ecobli ) * sin ( raddeg * m_body.eclong );
|
||||
double bottom = cos ( raddeg * m_body.eclong );
|
||||
m_body.rascen = clamp_circular( radtodeg * std::atan2( top, bottom ) );
|
||||
|
||||
m_body.rascen = degrad * atan2( top, bottom );
|
||||
if( m_body.rascen < 0.0 ) m_body.rascen += 360.0; // (make it a positive angle)
|
||||
// Greenwich mean sidereal time
|
||||
m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime;
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
|
||||
// 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)
|
||||
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 cz; // cosine of the solar zenith angle
|
||||
|
||||
double tdatcd = cos( raddeg * m_body.declin );
|
||||
double tdatch = cos( raddeg * m_body.hrang );
|
||||
double tdatcl = cos( raddeg * m_observer.latitude );
|
||||
double tdatsd = sin( raddeg * m_body.declin );
|
||||
double tdatsl = sin( raddeg * m_observer.latitude );
|
||||
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;
|
||||
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; }
|
||||
if( fabs( cz ) > 1.0 ) { cz >= 0.0 ? cz = 1.0 : cz = -1.0; }
|
||||
|
||||
m_body.zenetr = acos( cz ) * degrad;
|
||||
m_body.elevetr = 90.0 - m_body.zenetr;
|
||||
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 );
|
||||
m_body.zenetr = std::acos( cz ) * radtodeg;
|
||||
m_body.elevetr = 90.0 - m_body.zenetr;
|
||||
refract();
|
||||
}
|
||||
|
||||
void cSun::refract() {
|
||||
@@ -258,10 +258,9 @@ void cSun::irradiance() {
|
||||
static double degrad = 57.295779513; // converts from radians to degrees
|
||||
static double raddeg = 0.0174532925; // converts from degrees to radians
|
||||
|
||||
SYSTEMTIME localtime; // time for the calculation
|
||||
time( &localtime );
|
||||
auto const &localtime = Simulation::Time.data(); // time for the calculation
|
||||
|
||||
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 cd = cos( raddeg * m_body.dayang ); // cosine of the day angle or delination
|
||||
m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd;
|
||||
@@ -282,50 +281,3 @@ void cSun::irradiance() {
|
||||
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 );
|
||||
}
|
||||
|
||||
42
sun.h
42
sun.h
@@ -54,35 +54,31 @@ protected:
|
||||
void refract();
|
||||
// calculates light intensity at current moment
|
||||
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:
|
||||
GLUquadricObj *sunsphere; // temporary handler for sun positioning test
|
||||
|
||||
struct celestialbody { // main planet parameters
|
||||
|
||||
double dayang; // day angle (daynum*360/year-length) degrees
|
||||
double mnlong; // mean longitude, degrees
|
||||
double mnanom; // mean anomaly, degrees
|
||||
double eclong; // ecliptic longitude, degrees.
|
||||
double ecobli; // 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
|
||||
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
|
||||
|
||||
17
usefull.h
17
usefull.h
@@ -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))
|
||||
|
||||
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;
|
||||
if( value < Min ) { value = Min; }
|
||||
@@ -43,8 +44,20 @@ _Type clamp( _Type const Value, _Type const Min, _Type const Max ) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// keeps the provided value in specified range 0-Range, as if the range was circular buffer
|
||||
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 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user