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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

128
World.cpp
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

19
sun.cpp
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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