16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-19 05:29:17 +02:00

Merged branch mover_in_c++ into master

This commit is contained in:
firleju
2017-02-28 17:05:51 +01:00
41 changed files with 2483 additions and 612 deletions

View File

@@ -22,7 +22,7 @@ http://mozilla.org/MPL/2.0/.
#include "Timer.h"
#include "MdlMngr.h"
// McZapkie:
#include "Texture.h"
#include "renderer.h"
//---------------------------------------------------------------------------
TAnimContainer *TAnimModel::acAnimList = NULL;
@@ -449,9 +449,9 @@ bool TAnimModel::Init(std::string const &asName, std::string const &asReplacable
asText = asReplacableTexture.substr(1, asReplacableTexture.length() - 1); // zapamiętanie tekstu
else if (asReplacableTexture != "none")
ReplacableSkinId[1] =
TextureManager.GetTextureId( asReplacableTexture, "" );
GfxRenderer.GetTextureId( asReplacableTexture, "" );
if( ( ReplacableSkinId[ 1 ] != 0 )
&& ( TextureManager.Texture( ReplacableSkinId[ 1 ] ).has_alpha ) ) {
&& ( GfxRenderer.Texture( ReplacableSkinId[ 1 ] ).has_alpha ) ) {
// tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych
iTexAlpha = 0x31310031;
}

View File

@@ -146,7 +146,7 @@ int Console::On()
{ // załączenie konsoli (np. nawiązanie komunikacji)
iSwitch[0] = iSwitch[1] = iSwitch[2] = iSwitch[3] = 0; // bity 0..127 - bez [Ctrl]
iSwitch[4] = iSwitch[5] = iSwitch[6] = iSwitch[7] = 0; // bity 128..255 - z [Ctrl]
switch (iMode)
switch (iMode)
{
case 1: // kontrolki klawiatury
case 2: // kontrolki klawiatury
@@ -176,6 +176,7 @@ int Console::On()
{ // połączenie nie wyszło, ma być NULL
delete PoKeys55[0];
PoKeys55[0] = NULL;
WriteLog("PoKeys not found!");
}
break;
}
@@ -324,29 +325,29 @@ void Console::BitsUpdate(int mask)
else MWDComm->WriteDataBuff[4] &= ~(1 << 6);
if (mask & 0x0004) if (iBits & 4) MWDComm->WriteDataBuff[4] |= 1 << 1; // jazda na oporach rozruchowych
else MWDComm->WriteDataBuff[4] &= ~(1 << 1);
if (mask & 0x0008) if (iBits & 8) MWDComm->WriteDataBuff[5] |= 1 << 5; // wy??cznik szybki
if (mask & 0x0008) if (iBits & 8) MWDComm->WriteDataBuff[5] |= 1 << 5; // wyłącznik szybki
else MWDComm->WriteDataBuff[5] &= ~(1 << 5);
if (mask & 0x0010) if (iBits & 0x10) MWDComm->WriteDataBuff[5] |= 1 << 4; // nadmiarowy silnik?w trakcyjnych
if (mask & 0x0010) if (iBits & 0x10) MWDComm->WriteDataBuff[5] |= 1 << 4; // nadmiarowy silników trakcyjnych
else MWDComm->WriteDataBuff[5] &= ~(1 << 4);
if (mask & 0x0020) if (iBits & 0x20) MWDComm->WriteDataBuff[4] |= 1 << 0; // styczniki liniowe
if (mask & 0x0020) if (iBits & 0x20) MWDComm->WriteDataBuff[5] |= 1 << 0; // styczniki liniowe
else MWDComm->WriteDataBuff[5] &= ~(1 << 0);
if (mask & 0x0040) if (iBits & 0x40) MWDComm->WriteDataBuff[4] |= 1 << 2; // po?lizg
if (mask & 0x0040) if (iBits & 0x40) MWDComm->WriteDataBuff[4] |= 1 << 2; // poślizg
else MWDComm->WriteDataBuff[4] &= ~(1 << 2);
if (mask & 0x0080) if (iBits & 0x80) MWDComm->WriteDataBuff[5] |= 1 << 2; // (nadmiarowy) przetwornicy? ++
else MWDComm->WriteDataBuff[5] &= ~(1 << 2);
if (mask & 0x0100) if (iBits & 0x100) MWDComm->WriteDataBuff[5] |= 1 << 7; // nadmiarowy spr??arki
if (mask & 0x0100) if (iBits & 0x100) MWDComm->WriteDataBuff[5] |= 1 << 7; // nadmiarowy sprężarki
else MWDComm->WriteDataBuff[5] &= ~(1 << 7);
if (mask & 0x0200) if (iBits & 0x200) MWDComm->WriteDataBuff[2] |= 1 << 1; // wentylatory i opory
else MWDComm->WriteDataBuff[2] &= ~(1 << 1);
if (mask & 0x0400) if (iBits & 0x400) MWDComm->WriteDataBuff[2] |= 1 << 2; // wysoki rozruch
else MWDComm->WriteDataBuff[2] &= ~(1 << 2);
if (mask & 0x0800) if (iBits & 0x800) MWDComm->WriteDataBuff[4] |= 1 << 0; // ogrzewanie poci?gu
if (mask & 0x0800) if (iBits & 0x800) MWDComm->WriteDataBuff[4] |= 1 << 0; // ogrzewanie pociągu
else MWDComm->WriteDataBuff[4] &= ~(1 << 0);
if (mask & 0x1000) if (iBits & 0x1000) MWDComm->bHamowanie = true; // hasler: ci?nienie w hamulcach HASLER rysik 2
if (mask & 0x1000) if (iBits & 0x1000) MWDComm->bHamowanie = true; // hasler: ciśnienie w hamulcach HASLER rysik 2
else MWDComm->bHamowanie = false;
if (mask & 0x2000) if (iBits & 0x2000) MWDComm->WriteDataBuff[6] |= 1 << 4; // hasler: pr?d "na" silnikach HASLER rysik 3
if (mask & 0x2000) if (iBits & 0x2000) MWDComm->WriteDataBuff[6] |= 1 << 4; // hasler: prąd "na" silnikach - HASLER rysik 3
else MWDComm->WriteDataBuff[6] &= ~(1 << 4);
if (mask & 0x4000) if (iBits & 0x4000) MWDComm->WriteDataBuff[6] |= 1 << 7; // brz?czyk SHP/CA
if (mask & 0x4000) if (iBits & 0x4000) MWDComm->WriteDataBuff[6] |= 1 << 7; // brzęczyk SHP/CA
else MWDComm->WriteDataBuff[6] &= ~(1 << 7);
//if(mask & 0x8000) if(iBits & 0x8000) MWDComm->WriteDataBuff[1] |= 1<<7; (puste)
//else MWDComm->WriteDataBuff[0] &= ~(1<<7);
@@ -393,36 +394,50 @@ void Console::ValueSet(int x, double y)
unsigned int iliczba;
switch (x)
{
case 0: iliczba = (unsigned int)floor((y / (Global::fMWDzg[0] * 10) * Global::fMWDzg[1]) + 0.5); // zbiornik g??wny
case 0: iliczba = (unsigned int)floor((y / (Global::fMWDzg[0] * 10) * Global::fMWDzg[1]) + 0.5); // zbiornik główny
MWDComm->WriteDataBuff[12] = (unsigned char)(iliczba >> 8);
MWDComm->WriteDataBuff[11] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Main tank press " + to_string(MWDComm->WriteDataBuff[12]) + " " + to_string(MWDComm->WriteDataBuff[11]));
break;
case 1: iliczba = (unsigned int)floor((y / (Global::fMWDpg[0] * 10) * Global::fMWDpg[1]) + 0.5); // przew?d g??wny
case 1: iliczba = (unsigned int)floor((y / (Global::fMWDpg[0] * 10) * Global::fMWDpg[1]) + 0.5); // przewód główny
MWDComm->WriteDataBuff[10] = (unsigned char)(iliczba >> 8);
MWDComm->WriteDataBuff[9] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Main pipe press " + to_string(MWDComm->WriteDataBuff[10]) + " " + to_string(MWDComm->WriteDataBuff[9]));
break;
case 2: iliczba = (unsigned int)floor((y / (Global::fMWDph[0] * 10) * Global::fMWDph[1]) + 0.5); // cylinder hamulcowy
case 2: iliczba = (unsigned int)floor((y / (Global::fMWDph[0] * 10) * Global::fMWDph[1]) + 0.5); // cylinder hamulcowy
MWDComm->WriteDataBuff[8] = (unsigned char)(iliczba >> 8);
MWDComm->WriteDataBuff[7] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Break press " + to_string(MWDComm->WriteDataBuff[8]) + " " + to_string(MWDComm->WriteDataBuff[7]));
break;
case 3: iliczba = (unsigned int)floor((y / Global::fMWDvolt[0] * Global::fMWDvolt[1]) + 0.5); // woltomierz WN
case 3: iliczba = (unsigned int)floor((y / Global::fMWDvolt[0] * Global::fMWDvolt[1]) + 0.5); // woltomierz WN
MWDComm->WriteDataBuff[14] = (unsigned char)(iliczba >> 8);
MWDComm->WriteDataBuff[13] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Hi Volt meter " + to_string(MWDComm->WriteDataBuff[14]) + " " + to_string(MWDComm->WriteDataBuff[13]));
break;
case 4: iliczba = (unsigned int)floor((y / Global::fMWDamp[0] * Global::fMWDamp[1]) + 0.5); // amp WN 1
MWDComm->WriteDataBuff[16] = (unsigned char)(iliczba >> 8);
MWDComm->WriteDataBuff[15] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Apm meter1 " + to_string(MWDComm->WriteDataBuff[16]) + " " + to_string(MWDComm->WriteDataBuff[15]));
break;
case 5: iliczba = (unsigned int)floor((y / Global::fMWDamp[0] * Global::fMWDamp[1]) + 0.5); // amp WN 2
MWDComm->WriteDataBuff[18] = (unsigned char)(iliczba >> 8);
MWDComm->WriteDataBuff[17] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Apm meter2 " + to_string(MWDComm->WriteDataBuff[18]) + " " + to_string(MWDComm->WriteDataBuff[17]));
break;
case 6: iliczba = (unsigned int)floor((y / Global::fMWDamp[0] * Global::fMWDamp[1]) + 0.5); // amp WN 3
MWDComm->WriteDataBuff[20] = (unsigned int)(iliczba >> 8);
MWDComm->WriteDataBuff[19] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Apm meter3 " + to_string(MWDComm->WriteDataBuff[20]) + " " + to_string(MWDComm->WriteDataBuff[19]));
break;
case 7: MWDComm->WriteDataBuff[0] = (unsigned char)floor(y); // prędkość
case 7: if (Global::iPause) MWDComm->WriteDataBuff[0] = 0; //skoro pauza to hasler stoi i nie nabija kilometrów CHYBA NIE DZIAŁA!
else MWDComm->WriteDataBuff[0] = (unsigned char)floor(y); // prędkość dla np haslera
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Speed: " + to_string(MWDComm->WriteDataBuff[0]));
break;
case 8: iliczba = (unsigned int)floor((y / Global::fMWDlowVolt[0] * Global::fMWDlowVolt[1]) + 0.5); // volt NN
MWDComm->WriteDataBuff[22] = (unsigned int)(iliczba >> 8);
MWDComm->WriteDataBuff[21] = (unsigned char)iliczba;
if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Low Volt meter " + to_string(MWDComm->WriteDataBuff[22]) + " " + to_string(MWDComm->WriteDataBuff[21]));
break; // przygotowane do wdrożenia, jeszcze nie wywoływane
}
}
};
@@ -461,29 +476,31 @@ float Console::AnalogCalibrateGet(int x)
{ // pobranie i kalibracja wartości analogowej, jeśli nie ma PoKeys zwraca NULL
if (iMode == 4 && PoKeys55[0])
{
float b = PoKeys55[0]->fAnalog[x];
return (((((Global::fCalibrateIn[x][5] * b) + Global::fCalibrateIn[x][4]) * b +
Global::fCalibrateIn[x][3]) *
b +
Global::fCalibrateIn[x][2]) *
b +
Global::fCalibrateIn[x][1]) *
b +
Global::fCalibrateIn[x][0];
}
float b = PoKeys55[0]->fAnalog[x];
/*return (((((Global::fCalibrateIn[x][5] * b) + Global::fCalibrateIn[x][4]) * b +
Global::fCalibrateIn[x][3]) *
b +
Global::fCalibrateIn[x][2]) *
b +
Global::fCalibrateIn[x][1]) *
b +
Global::fCalibrateIn[x][0];*/
b = (((((Global::fCalibrateIn[x][5] * b) + Global::fCalibrateIn[x][4]) * b +
Global::fCalibrateIn[x][3]) *
b +
Global::fCalibrateIn[x][2]) *
b +
Global::fCalibrateIn[x][1]) *
b +
Global::fCalibrateIn[x][0];
if (x == 0) return (b + 2) / 8;
if (x == 1) return b/10;
else return b;
}
if (Global::bMWDmasterEnable && Global::bMWDBreakEnable)
{
float b = (float)MWDComm->uiAnalog[x];
b = (b - Global::fMWDAnalogInCalib[x][0]) / (Global::fMWDAnalogInCalib[x][1] - Global::fMWDAnalogInCalib[x][0]);
switch (x)
{
case 0: if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("Pozycja kranu = " + to_string(b * 8 - 2));
return (b * 8 - 2);
break;
case 1: return (b * 10);
break;
default: return 0;
}
return (b - Global::fMWDAnalogInCalib[x][0]) / (Global::fMWDAnalogInCalib[x][1] - Global::fMWDAnalogInCalib[x][0]);
}
return -1.0; // odcięcie
};

View File

@@ -152,7 +152,7 @@ bool TMWDComm::Close() // zamykanie portu COM
return TRUE;
}
inline bool TMWDComm::GetMWDState() // sprawdzanie otwarcia portu COM
bool TMWDComm::GetMWDState() // sprawdzanie otwarcia portu COM
{
if (hComm > 0)
return 1;
@@ -164,7 +164,7 @@ bool TMWDComm::ReadData() // odbieranie danych + odczyta danych analogowych i za
{
DWORD bytes_read;
ReadFile(hComm, &ReadDataBuff[0], BYTETOREAD, &bytes_read, NULL);
if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog("Data receive. Checking data...");
if (Global::bMWDBreakEnable)
{
uiAnalog[0] = (ReadDataBuff[9] << 8) + ReadDataBuff[8];
@@ -204,8 +204,11 @@ bool TMWDComm::Run() // wywoływanie obsługi MWD + generacja większego opóźn
if (!(MWDTime % Global::iMWDdivider))
{
MWDTime = 0;
if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog("Sending data...");
SendData();
if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog(" complet!\nReceiving data...");
ReadData();
if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog(" complet!");
return 1;
}
}
@@ -231,43 +234,43 @@ void TMWDComm::CheckData() // sprawdzanie wejść cyfrowych i odpowiednie sterow
/*
Rozpiska portów!
Port0: 0 NC odblok. przek. sprężarki i wentyl. oporów
1 M wyłącznik wył. szybkiego
2 Shift+M impuls załączający wył. szybki
3 N odblok. przekaźników nadmiarowych
1 M wyłącznik wył. szybkiego
2 Shift+M impuls załączający wył. szybki
3 N odblok. przekaźników nadmiarowych
i różnicowego obwodu głównego
4 NC rezerwa
5 Ctrl+N odblok. przek. nadmiarowych
4 NC rezerwa
5 Ctrl+N odblok. przek. nadmiarowych
przetwornicy, ogrzewania pociągu i różnicowych obw. pomocniczych
6 L wył. styczników liniowych
7 SPACE kasowanie czuwaka
6 L wył. styczników liniowych
7 SPACE kasowanie czuwaka
Port1: 0 NC
1 (Shift) X przetwornica
2 (Shift) C sprężarka
3 S piasecznice
4 (Shift) H ogrzewanie składu
5 przel. hamowania Shift+B
1 (Shift) X przetwornica
2 (Shift) C sprężarka
3 S piasecznice
4 (Shift) H ogrzewanie składu
5 przel. hamowania Shift+B
pspbpwy Ctrl+B pospieszny B towarowy
6 przel. hamowania
7 (Shift) F rozruch w/n
6 przel. hamowania
7 (Shift) F rozruch w/n
Port2: 0 (Shift) P pantograf przedni
1 (Shift) O pantograf tylni
2 ENTER przyhamowanie przy poślizgu
3 () przyciemnienie świateł
4 () przyciemnienie świateł
5 NUM6 odluźniacz
6 a syrena lok W
7 A syrena lok N
1 (Shift) O pantograf tylni
2 ENTER przyhamowanie przy poślizgu
3 () przyciemnienie świateł
4 () przyciemnienie świateł
5 NUM6 odluźniacz
6 a syrena lok W
7 A syrena lok N
Port3: 0 Shift+J bateria
1
2
3
4
5
6
7
1
2
3
4
5
6
7
*/
/* po przełączeniu bistabilnego najpierw wciskamy klawisz i przy następnym

View File

@@ -61,8 +61,8 @@ public:
unsigned int uiAnalog[4]; // trzymanie danych z wejść analogowych
BYTE ReadDataBuff[BYTETOREAD]; //17]; // bufory danych
BYTE WriteDataBuff[BYTETOWRITE]; //31];
BYTE ReadDataBuff[BYTETOREAD+2]; //17]; // bufory danych
BYTE WriteDataBuff[BYTETOWRITE+2]; //31];
TMWDComm(); // konstruktor
~TMWDComm(); // destruktor
@@ -70,43 +70,29 @@ public:
#endif
/*
INFO - zmiany dokonane w innych plikach niezbędne do prawidłowego działania:
INFO - wpisy do eu07.ini:
Console.cpp:
Console::AnalogCalibrateGet - obsługa kranów hamulców
Console::Update - wywoływanie obsługi MWD
Console::ValueSet - obsługa manometrów, mierników WN (PWM-y)
Console::BitsUpdate - ustawiania lampek
Console::Off - zamykanie portu COM
Console::On - otwieranie portu COM
Console::~Console - usuwanie MWD (jest też w Console OFF)
mwdmasterenable yes // włącz MWD (master MWD Enable)
mwddebugenable yes // włącz logowanie
mwddebugmode 4 // tryb debugowania (które logi)
MWDComm * Console::MWD = NULL; - luzem, obiekt i wskaźnik(?)
dodatkowo zmieniłem int na long int dla BitSet i BitClear oraz iBits
mwdcomportname COM3 // nazwa portu
mwdbaudrate 500000 // prędkość transmisji
Train.cpp:
if (Global::iFeedbackMode == 5) - pobieranie prędkości, manometrów i mierników WN
if (ggBrakeCtrl.SubModel) - możliwość sterowania hamulcem zespolonym
if (ggLocalBrake.SubModel) - możliwość sterowania hamulcem lokomotywy
mwdinputenable yes // włącz wejścia (przyciski, przełączniki)
mwdbreakenable yes // włącz hamulce (wejścia analogowe)
Globals.h:
dodano zmienne dla MWD
Globals.cpp:
dodano inicjalizaję zmiennych i odczyt z ini ustawień
mwdmainbreakconfig 0 1023 // konfiguracja kranu zespolonego -> min, max (położenie kranu - odczyt z ADC)
mwdlocbreakconfig 0 1023 // konfiguracja kranu maszynisty -> min, max (położenie kranu - odczyt z ADC)
mwdanalogin2config 0 1023
mwdanalogin2config 0 1023
Wpisy do pliku eu07.ini
mwdmaintankpress 0.9 1023 // max ciśnienie w zbiorniku głownym i rozdzielczość
mwdmainpipepress 0.7 1023 // max ciśnienie w przewodzie głównym i rozdzielczość
mwdbreakpress 0.5 1023 // max ciśnienie w cylindrach hamulcowych i rozdzielczość
//maciek001 MWD
comportname COM3 // wybór portu COM
mwdbaudrate 500000
mwdhivoltmeter 4000 1023 // max napięcie na woltomierzu WN
mwdhiampmeter 800 1023 // max prąd amperomierza WN
mwdbreakenable yes // czy załączyć sterowanie hamulcami? blokuje klawiature
mwdbreak 1 255 0 255 // hamulec zespolony
mwdbreak 2 255 0 255 // hamulec lokomotywy
mwdzbiornikglowny 0.82 255
mwdprzewodglowny 0.7 255
mwdcylinderhamulcowy 0.43 255
mwdwoltomierzwn 4000 255
mwdamperomierzwn 800 255
mwddivider 5 // dzielnik - czym większy tym rzadziej czyta diwajs
*/

View File

@@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/.
#include "Usefull.h"
// McZapkie-260202
#include "Globals.h"
#include "Texture.h"
#include "renderer.h"
#include "AirCoupler.h"
#include "TractionPower.h"
@@ -3710,7 +3710,7 @@ void TDynamicObject::Render()
// zmienne
renderme = false;
// przeklejka
double ObjSqrDist = SquareMagnitude(Global::pCameraPosition - vPosition);
double ObjSqrDist = SquareMagnitude(Global::pCameraPosition - vPosition) / Global::ZoomFactor;
// koniec przeklejki
if (ObjSqrDist < 500) // jak jest blisko - do 70m
modelrotate = 0.01; // mały kąt, żeby nie znikało
@@ -3737,7 +3737,7 @@ void TDynamicObject::Render()
{
TSubModel::iInstance = (int)this; //żeby nie robić cudzych animacji
// AnsiString asLoadName="";
double ObjSqrDist = SquareMagnitude(Global::pCameraPosition - vPosition);
double ObjSqrDist = SquareMagnitude(Global::pCameraPosition - vPosition) / Global::ZoomFactor;
ABuLittleUpdate(ObjSqrDist); // ustawianie zmiennych submodeli dla wspólnego modelu
// Cone(vCoulpler[0],modelRot.z,0);
@@ -3760,12 +3760,14 @@ void TDynamicObject::Render()
// double ObjDist= SquareMagnitude(Global::pCameraPosition-pos);
if (this == Global::pUserDynamic)
{ // specjalne ustawienie, aby nie trzęsło
#ifdef EU07_USE_OLD_LIGHTING_MODEL
if (Global::bSmudge)
{ // jak jest widoczna smuga, to pojazd renderować po
// wyrenderowaniu smugi
glPopMatrix(); // a to trzeba zebrać przed wyjściem
return;
}
#endif
// if (Global::pWorld->) //tu trzeba by ustawić animacje na modelu
// zewnętrznym
glLoadIdentity(); // zacząć od macierzy jedynkowej
@@ -3775,6 +3777,8 @@ void TDynamicObject::Render()
glTranslated(vPosition.x, vPosition.y,
vPosition.z); // standardowe przesunięcie względem początku scenerii
glMultMatrixd(mMatrix.getArray());
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
if (fShade > 0.0)
{ // Ra: zmiana oswietlenia w tunelu, wykopie
GLfloat ambientLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
@@ -3791,6 +3795,7 @@ void TDynamicObject::Render()
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
}
#endif
if (Global::bUseVBO)
{ // wersja VBO
if (mdLowPolyInt)
@@ -3804,9 +3809,26 @@ void TDynamicObject::Render()
}
else
{ // wersja Display Lists
if (mdLowPolyInt)
if (FreeFlyModeFlag ? true : !mdKabina || !bDisplayCab)
mdLowPolyInt->Render(ObjSqrDist, ReplacableSkinID, iAlpha);
if( mdLowPolyInt ) {
// low poly interior
if( FreeFlyModeFlag ? true : !mdKabina || !bDisplayCab ) {
// enable cab light if needed
if( InteriorLightLevel > 0.0f ) {
// crude way to light the cabin, until we have something more complete in place
auto const cablight = InteriorLight * InteriorLightLevel;
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x );
}
mdLowPolyInt->Render( ObjSqrDist, ReplacableSkinID, iAlpha );
if( InteriorLightLevel > 0.0f ) {
// reset the overall ambient
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
}
}
}
mdModel->Render(ObjSqrDist, ReplacableSkinID, iAlpha);
if (mdLoad) // renderowanie nieprzezroczystego ładunku
mdLoad->Render(ObjSqrDist, ReplacableSkinID, iAlpha);
@@ -3823,6 +3845,8 @@ void TDynamicObject::Render()
// ma byc wyswietlana
// ABu: tylko w trybie FreeFly, zwykly tryb w world.cpp
// Ra: świetła są ustawione dla zewnętrza danego pojazdu
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-mplement this
// oswietlenie kabiny
GLfloat ambientCabLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat diffuseCabLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
@@ -3858,20 +3882,25 @@ void TDynamicObject::Render()
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientCabLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseCabLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularCabLight);
#endif
if (Global::bUseVBO)
mdKabina->RaRender(ObjSqrDist, 0);
else
mdKabina->Render(ObjSqrDist, 0);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
#endif
}
if (fShade != 0.0) // tylko jeśli było zmieniane
#ifdef EU07_USE_OLD_LIGHTING_MODEL
if( fShade != 0.0 ) // tylko jeśli było zmieniane
{ // przywrócenie standardowego oświetlenia
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
}
#endif
glPopMatrix();
if (btnOn)
TurnOff(); // przywrócenie domyślnych pozycji submodeli
@@ -4269,6 +4298,8 @@ void TDynamicObject::RenderAlpha()
glTranslated(vPosition.x, vPosition.y,
vPosition.z); // standardowe przesunięcie względem początku scenerii
glMultMatrixd(mMatrix.getArray());
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
if (fShade > 0.0)
{ // Ra: zmiana oswietlenia w tunelu, wykopie
GLfloat ambientLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
@@ -4285,6 +4316,7 @@ void TDynamicObject::RenderAlpha()
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
}
#endif
if (Global::bUseVBO)
{ // wersja VBO
if (mdLowPolyInt)
@@ -4307,63 +4339,15 @@ void TDynamicObject::RenderAlpha()
// if (mdPrzedsionek) //Ra: przedsionków tu wcześniej nie było - włączyć?
// mdPrzedsionek->RenderAlpha(ObjSqrDist,ReplacableSkinID,iAlpha);
}
/* skoro false to można wyciąc
//ABu: Tylko w trybie freefly
if (false)//((mdKabina!=mdModel) && bDisplayCab && FreeFlyModeFlag)
{
//oswietlenie kabiny
GLfloat ambientCabLight[4]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat diffuseCabLight[4]= { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat specularCabLight[4]= { 0.5f, 0.5f, 0.5f, 1.0f };
for (int li=0; li<3; li++)
{
ambientCabLight[li]= Global::ambientDayLight[li]*0.9;
diffuseCabLight[li]= Global::diffuseDayLight[li]*0.5;
specularCabLight[li]= Global::specularDayLight[li]*0.5;
}
switch (MyTrack->eEnvironment)
{
case e_canyon:
{
for (int li=0; li<3; li++)
{
diffuseCabLight[li]*= 0.6;
specularCabLight[li]*= 0.8;
}
}
break;
case e_tunnel:
{
for (int li=0; li<3; li++)
{
ambientCabLight[li]*= 0.3;
diffuseCabLight[li]*= 0.1;
specularCabLight[li]*= 0.2;
}
}
break;
}
// dorobic swiatlo od drugiej strony szyby
glLightfv(GL_LIGHT0,GL_AMBIENT,ambientCabLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseCabLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,specularCabLight);
mdKabina->RenderAlpha(ObjSqrDist,0);
//smierdzi
// mdModel->RenderAlpha(SquareMagnitude(Global::pCameraPosition-pos),0);
glLightfv(GL_LIGHT0,GL_AMBIENT,Global::ambientDayLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,Global::diffuseDayLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,Global::specularDayLight);
}
*/
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
if (fShade != 0.0) // tylko jeśli było zmieniane
{ // przywrócenie standardowego oświetlenia
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
}
#endif
glPopMatrix();
if (btnOn)
TurnOff(); // przywrócenie domyślnych pozycji submodeli
@@ -4428,7 +4412,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
Global::asCurrentTexturePath + ReplacableSkin; // skory tez z dynamic/...
std::string x = TextureTest(Global::asCurrentTexturePath + "nowhere"); // na razie prymitywnie
if (!x.empty())
ReplacableSkinID[4] = TextureManager.GetTextureId( Global::asCurrentTexturePath + "nowhere", "", 9);
ReplacableSkinID[4] = GfxRenderer.GetTextureId( Global::asCurrentTexturePath + "nowhere", "", 9);
/*
if ((i = ReplacableSkin.Pos("|")) > 0) // replacable dzielone
{
@@ -4491,21 +4475,21 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
*/
if (iMultiTex > 0)
{ // jeśli model ma 4 tekstury
ReplacableSkinID[1] = TextureManager.GetTextureId(
ReplacableSkinID[1] = GfxRenderer.GetTextureId(
ReplacableSkin + ",1", "", Global::iDynamicFiltering);
if (ReplacableSkinID[1])
{ // pierwsza z zestawu znaleziona
ReplacableSkinID[2] = TextureManager.GetTextureId(
ReplacableSkinID[2] = GfxRenderer.GetTextureId(
ReplacableSkin + ",2", "", Global::iDynamicFiltering);
if (ReplacableSkinID[2])
{
iMultiTex = 2; // już są dwie
ReplacableSkinID[3] = TextureManager.GetTextureId(
ReplacableSkinID[3] = GfxRenderer.GetTextureId(
ReplacableSkin + ",3", "", Global::iDynamicFiltering);
if (ReplacableSkinID[3])
{
iMultiTex = 3; // a teraz nawet trzy
ReplacableSkinID[4] = TextureManager.GetTextureId(
ReplacableSkinID[4] = GfxRenderer.GetTextureId(
ReplacableSkin + ",4", "", Global::iDynamicFiltering);
if (ReplacableSkinID[4])
iMultiTex = 4; // jak są cztery, to blokujemy podmianę tekstury
@@ -4516,14 +4500,14 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
else
{ // zestaw nie zadziałał, próbujemy normanie
iMultiTex = 0;
ReplacableSkinID[1] = TextureManager.GetTextureId(
ReplacableSkinID[1] = GfxRenderer.GetTextureId(
ReplacableSkin, "", Global::iDynamicFiltering);
}
}
else
ReplacableSkinID[1] = TextureManager.GetTextureId(
ReplacableSkinID[1] = GfxRenderer.GetTextureId(
ReplacableSkin, "", Global::iDynamicFiltering);
if (TextureManager.Texture(ReplacableSkinID[1]).has_alpha)
if (GfxRenderer.Texture(ReplacableSkinID[1]).has_alpha)
iAlpha = 0x31310031; // tekstura -1 z kanałem alfa - nie renderować w cyklu
// nieprzezroczystych
else
@@ -4531,17 +4515,17 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
// renderować w
// cyklu przezroczystych
if (ReplacableSkinID[2])
if (TextureManager.Texture(ReplacableSkinID[2]).has_alpha)
if (GfxRenderer.Texture(ReplacableSkinID[2]).has_alpha)
iAlpha |= 0x02020002; // tekstura -2 z kanałem alfa - nie renderować
// w cyklu
// nieprzezroczystych
if (ReplacableSkinID[3])
if (TextureManager.Texture(ReplacableSkinID[3]).has_alpha)
if (GfxRenderer.Texture(ReplacableSkinID[3]).has_alpha)
iAlpha |= 0x04040004; // tekstura -3 z kanałem alfa - nie renderować
// w cyklu
// nieprzezroczystych
if (ReplacableSkinID[4])
if (TextureManager.Texture(ReplacableSkinID[4]).has_alpha)
if (GfxRenderer.Texture(ReplacableSkinID[4]).has_alpha)
iAlpha |= 0x08080008; // tekstura -4 z kanałem alfa - nie renderować
// w cyklu
// nieprzezroczystych
@@ -5854,13 +5838,13 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer)
std::string x = TextureTest(asBaseDir + numer + "@" + MoverParameters->TypeName);
if (!x.empty())
{
ReplacableSkinID[4] = TextureManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
return;
}
x = TextureTest(asBaseDir + numer );
if (!x.empty())
{
ReplacableSkinID[4] = TextureManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
return;
}
if (to.empty())
@@ -5868,17 +5852,17 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer)
x = TextureTest(asBaseDir + to + "@" + MoverParameters->TypeName); // w pierwszej kolejności z nazwą FIZ/MMD
if (!x.empty())
{
ReplacableSkinID[4] = TextureManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
return;
}
x = TextureTest(asBaseDir + to); // na razie prymitywnie
if (!x.empty())
ReplacableSkinID[4] = TextureManager.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
else
{
x = TextureTest(asBaseDir + "nowhere"); // jak nie znalazł dedykowanej, to niech daje nowhere
if (!x.empty())
ReplacableSkinID[4] = TextureManager.GetTextureId( x, "", 9);
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9);
}
// Ra 2015-01: żeby zalogować błąd, trzeba by mieć pewność, że model używa
// tekstury nr 4

View File

@@ -140,11 +140,10 @@ class TAnim
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class TDynamicObject
{ // klasa pojazdu
private: // położenie pojazdu w świecie oraz parametry ruchu
class TDynamicObject { // klasa pojazdu
private: // położenie pojazdu w świecie oraz parametry ruchu
vector3 vPosition; // Ra: pozycja pojazdu liczona zaraz po przesunięciu
vector3 vCoulpler[2]; // współrzędne sprzęgów do liczenia zderzeń czołowych
vector3 vCoulpler[ 2 ]; // współrzędne sprzęgów do liczenia zderzeń czołowych
vector3 vUp, vFront, vLeft; // wektory jednostkowe ustawienia pojazdu
int iDirection; // kierunek pojazdu względem czoła składu (1=zgodny,0=przeciwny)
TTrackShape ts; // parametry toru przekazywane do fizyki
@@ -156,10 +155,10 @@ class TDynamicObject
float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia
vector3 modelRot; // obrot pudła względem świata - do przeanalizowania, czy potrzebne!!!
// bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów
TDynamicObject * ABuFindNearestObject(TTrack *Track, TDynamicObject *MyPointer,
int &CouplNr);
TDynamicObject * ABuFindNearestObject( TTrack *Track, TDynamicObject *MyPointer,
int &CouplNr );
public: // parametry położenia pojazdu dostępne publicznie
public: // parametry położenia pojazdu dostępne publicznie
std::string asTrack; // nazwa toru początkowego; wywalić?
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
@@ -175,12 +174,14 @@ class TDynamicObject
private:
// returns type of the nearest functional power source present in the trainset
public: // modele składowe pojazdu
public: // modele składowe pojazdu
TModel3d *mdModel; // model pudła
TModel3d *mdLoad; // model zmiennego ładunku
TModel3d *mdPrzedsionek; // model przedsionków dla EZT - może użyć mdLoad zamiast?
TModel3d *mdKabina; // model kabiny dla użytkownika; McZapkie-030303: to z train.h
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
float3 InteriorLight{ 0.9f * 255.0f / 255.0f, 0.9f * 216.0f / 255.0f, 0.9f * 176.0f / 255.0f }; // tungsten light. TODO: allow definition of light type?
float InteriorLightLevel{ 0.0f }; // current level of interior lighting
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
@@ -419,7 +420,7 @@ private:
void Render();
void RenderAlpha();
void RenderSounds();
inline vector3 GetPosition()
inline vector3 GetPosition() const
{
return vPosition;
};
@@ -435,7 +436,7 @@ private:
{
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition;
};
inline vector3 VectorFront()
inline vector3 VectorFront() const
{
return vFront;
};
@@ -455,7 +456,7 @@ private:
{
return MoverParameters->Vel;
};
inline double GetLength()
inline double GetLength() const
{
return MoverParameters->Dim.L;
};

View File

@@ -85,17 +85,19 @@ int InitGL(GLvoid) // All Setup For OpenGL Goes Here
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // resize and initialize the GL Window
{
WindowWidth = width;
WindowHeight = height;
Global::ScreenWidth = WindowWidth = width;
Global::ScreenHeight = WindowHeight = height;
if (height == 0) // prevent a divide by zero by
height = 1; // making height equal one
glViewport(0, 0, width, height); // Reset The Current Viewport
/*
glMatrixMode(GL_PROJECTION); // select the Projection Matrix
glLoadIdentity(); // reset the Projection Matrix
// calculate the aspect ratio of the window
gluPerspective(45.0f, (GLdouble)width / (GLdouble)height, 0.2f, 2500.0f);
glMatrixMode(GL_MODELVIEW); // select the Modelview Matrix
glLoadIdentity(); // reset the Modelview Matrix
*/
}
//---------------------------------------------------------------------------
@@ -509,6 +511,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, // handle for this window
if (DebugModeFlag)
{ // siatki wyświetlane tyko w trybie testowym
Global::bWireFrame = !Global::bWireFrame;
if( true == Global::bWireFrame ) {
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
}
else {
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
}
++Global::iReCompile; // odświeżyć siatki
// Ra: jeszcze usunąć siatki ze skompilowanych obiektów!
}
@@ -710,6 +718,9 @@ int WINAPI WinMain(HINSTANCE hInstance, // instance
fullscreen))
return 0; // quit if window was not created
SetForegroundWindow(hWnd);
GfxRenderer.Init();
// McZapkie: proba przeplukania klawiatury
Console *pConsole = new Console(); // Ra: nie wiem, czy ma to sens, ale jakoś zainicjowac trzeba
while (Console::Pressed(VK_F10))

View File

@@ -53,7 +53,10 @@ double inline float3::Length() const
{
return sqrt(x * x + y * y + z * z);
};
inline float3 operator/(const float3 &v, double k)
inline float3 operator*( float3 const &v, float const k ) {
return float3( v.x * k, v.y * k, v.z * k );
};
inline float3 operator/( float3 const &v, float const k )
{
return float3(v.x / k, v.y / k, v.z / k);
};
@@ -67,10 +70,19 @@ inline float3 SafeNormalize(const float3 &v)
retVal = v / l;
return retVal;
};
inline float3 CrossProduct(const float3 &v1, const float3 &v2)
inline float3 CrossProduct( float3 const &v1, float3 const &v2 )
{
return float3(v1.y * v2.z - v1.z * v2.y, v2.x * v1.z - v2.z * v1.x, v1.x * v2.y - v1.y * v2.x);
}
inline float DotProduct( float3 const &v1, float3 const &v2 ) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
inline float3 Interpolate( float3 const &First, float3 const &Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
class float4
{ // kwaternion obrotu

View File

@@ -175,14 +175,16 @@ void TGauge::Update()
*/ std::string n( "000000000" + std::to_string( static_cast<int>( std::floor( fValue ) ) ) );
if( n.length() > 10 ) { n.erase( 0, n.length() - 10 ); } // also dumb but should work for now
do
{ // pętla po submodelach potomnych i obracanie ich o kąt zależy od
// cyfry w (fValue)
if (sm->pName)
{ // musi mieć niepustą nazwę
if (sm->pName[0] >= '0')
if (sm->pName[0] <= '9')
sm->SetRotate(float3(0, 1, 0),
-36.0 * (n['0' + 10 - sm->pName[0]] - '0'));
{ // pętla po submodelach potomnych i obracanie ich o kąt zależy od cyfry w (fValue)
if( sm->pName ) {
// musi mieć niepustą nazwę
if( ( sm->pName[ 0 ] >= '0' )
&& ( sm->pName[ 0 ] <= '9' ) ) {
sm->SetRotate(
float3( 0, 1, 0 ),
-36.0 * ( n[ '0' + 9 - sm->pName[ 0 ] ] - '0' ) );
}
}
sm = sm->NextGet();
} while (sm);

View File

@@ -47,8 +47,13 @@ double Global::fOpenGL = 0.0; // wersja OpenGL - do sprawdzania obecności rozsz
bool Global::bOpenGL_1_5 = false; // czy są dostępne funkcje OpenGL 1.5
*/
double Global::fLuminance = 1.0; // jasność światła do automatycznego zapalania
float Global::SunAngle = 0.0f;
int Global::iReCompile = 0; // zwiększany, gdy trzeba odświeżyć siatki
HWND Global::hWnd = NULL; // uchwyt okna
int Global::ScreenWidth = 1;
int Global::ScreenHeight = 1;
float Global::ZoomFactor = 1.0f;
float Global::FieldOfView = 45.0f;
int Global::iCameraLast = -1;
std::string Global::asRelease = "16.0.1172.482";
std::string Global::asVersion =
@@ -90,12 +95,17 @@ double Global::fFogEnd = 2000;
float Global::Background[3] = {0.2, 0.4, 0.33};
GLfloat Global::AtmoColor[] = {0.423f, 0.702f, 1.0f};
GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
#ifdef EU07_USE_OLD_LIGHTING_MODEL
GLfloat Global::ambientDayLight[] = {0.40f, 0.40f, 0.45f, 1.0f}; // robocze
GLfloat Global::diffuseDayLight[] = {0.55f, 0.54f, 0.50f, 1.0f};
GLfloat Global::specularDayLight[] = {0.95f, 0.94f, 0.90f, 1.0f};
GLfloat Global::ambientLight[] = {0.80f, 0.80f, 0.85f, 1.0f}; // stałe
GLfloat Global::diffuseLight[] = {0.85f, 0.85f, 0.80f, 1.0f};
GLfloat Global::specularLight[] = {0.95f, 0.94f, 0.90f, 1.0f};
#else
opengl_light Global::DayLight;
int Global::DynamicLightCount{ 3 };
#endif
GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f};
GLfloat Global::noLight[] = {0.00f, 0.00f, 0.00f, 1.0f};
GLfloat Global::darkLight[] = {0.03f, 0.03f, 0.03f, 1.0f}; //śladowe
@@ -130,6 +140,7 @@ bool Global::bAdjustScreenFreq = true;
bool Global::bEnableTraction = true;
bool Global::bLoadTraction = true;
bool Global::bLiveTraction = true;
float Global::AnisotropicFiltering = 8.0f; // requested level of anisotropic filtering. TODO: move it to renderer object
int Global::iDefaultFiltering = 9; // domyślne rozmywanie tekstur TGA bez alfa
int Global::iBallastFiltering = 9; // domyślne rozmywanie tekstur podsypki
int Global::iRailProFiltering = 5; // domyślne rozmywanie tekstur szyn
@@ -204,6 +215,7 @@ double Global::fMWDpg[2] = { 0.8, 1023 };
double Global::fMWDph[2] = { 0.6, 1023 };
double Global::fMWDvolt[2] = { 4000, 1023 };
double Global::fMWDamp[2] = { 800, 1023 };
double Global::fMWDlowVolt[2] = { 150, 1023 };
int Global::iMWDdivider = 5;
//---------------------------------------------------------------------------
@@ -257,6 +269,14 @@ void Global::ConfigParse(cParser &Parser)
Parser.getTokens();
Parser >> Global::asHumanCtrlVehicle;
}
else if( token == "fieldofview" ) {
Parser.getTokens( 1, false );
Parser >> Global::FieldOfView;
// guard against incorrect values
Global::FieldOfView = std::min( 75.0f, Global::FieldOfView );
Global::FieldOfView = std::max( 15.0f, Global::FieldOfView );
}
else if (token == "width")
{
@@ -465,7 +485,12 @@ void Global::ConfigParse(cParser &Parser)
Parser.getTokens(1, false);
Parser >> Global::iDynamicFiltering;
}
else if (token == "usevbo")
else if( token == "anisotropicfiltering" ) {
Parser.getTokens( 1, false );
Parser >> Global::AnisotropicFiltering;
}
else if( token == "usevbo" )
{
Parser.getTokens();
@@ -551,18 +576,14 @@ void Global::ConfigParse(cParser &Parser)
std::tm *localtime = std::localtime(&timenow);
Global::fMoveLight = localtime->tm_yday + 1; // numer bieżącego dnia w roku
}
if (fMoveLight > 0.f) // tu jest nadal zwiększone o 1
{ // obliczenie deklinacji wg:
// http://naturalfrequency.com/Tregenza_Sharples/Daylight_Algorithms/algorithm_1_11.htm
// Spencer J W Fourier series representation of the position of the sun Search 2 (5)
// 172 (1971)
Global::fMoveLight =
M_PI / 182.5 * (Global::fMoveLight - 1.0); // numer dnia w postaci kąta
fSunDeclination =
0.006918 - 0.3999120 * std::cos(fMoveLight) + 0.0702570 * std::sin(fMoveLight) -
0.0067580 * std::cos(2 * fMoveLight) + 0.0009070 * std::sin(2 * fMoveLight) -
0.0026970 * std::cos(3 * fMoveLight) + 0.0014800 * std::sin(3 * fMoveLight);
}
}
else if( token == "dynamiclights" ) {
// number of dynamic lights in the scene
Parser.getTokens( 1, false );
Parser >> Global::DynamicLightCount;
// clamp the light number
Global::DynamicLightCount = std::min( 7, Global::DynamicLightCount ); // max 8 lights per opengl specs, and one used for sun
Global::DynamicLightCount = std::max( 1, Global::DynamicLightCount ); // at least one light for controlled vehicle
}
else if (token == "smoothtraction")
{
@@ -893,6 +914,11 @@ void Global::ConfigParse(cParser &Parser)
Parser >> fMWDamp[0] >> fMWDamp[1];
if (bMWDdebugEnable) WriteLog("Amp settings: " + to_string(fMWDamp[0]) + (" ") + to_string(fMWDamp[1]));
}
else if (token == "mwdlowvoltmeter") {
Parser.getTokens(2, false);
Parser >> fMWDlowVolt[0] >> fMWDlowVolt[1];
if (bMWDdebugEnable) WriteLog("Low VoltMeter settings: " + to_string(fMWDlowVolt[0]) + (" ") + to_string(fMWDlowVolt[1]));
}
else if (token == "mwddivider") {
Parser.getTokens(1, false);
Parser >> iMWDdivider;
@@ -931,9 +957,9 @@ void Global::ConfigParse(cParser &Parser)
/* this won't execute anymore with the old parser removed
// TBD: remove, or launch depending on passed flag?
if (qp)
{ // to poniżej wykonywane tylko raz, jedynie po wczytaniu eu07.ini
Console::ModeSet(iFeedbackMode, iFeedbackPort); // tryb pracy konsoli sterowniczej
iFpsRadiusMax = 0.000025 * fFpsRadiusMax *
{ // to poniżej wykonywane tylko raz, jedynie po wczytaniu eu07.ini*/
Console::ModeSet(iFeedbackMode, iFeedbackPort); // tryb pracy konsoli sterowniczej
/*iFpsRadiusMax = 0.000025 * fFpsRadiusMax *
fFpsRadiusMax; // maksymalny promień renderowania 3000.0 -> 225
if (iFpsRadiusMax > 400)
iFpsRadiusMax = 400;

View File

@@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/.
#include <string>
#include <Windows.h>
#include "renderer.h"
#include "opengl/glew.h"
#include "dumb3d.h"
@@ -220,12 +221,20 @@ class Global
static GLfloat AtmoColor[];
static GLfloat FogColor[];
// static bool bTimeChange;
#ifdef EU07_USE_OLD_LIGHTING_MODEL
static opengl_light AmbientLight;
static GLfloat ambientDayLight[];
static GLfloat diffuseDayLight[];
static GLfloat specularDayLight[];
static GLfloat ambientLight[];
static GLfloat diffuseLight[];
static GLfloat specularLight[];
#else
// TODO: put these things in the renderer
static opengl_light DayLight;
static int DynamicLightCount;
#endif
static GLfloat whiteLight[];
static GLfloat noLight[];
static GLfloat darkLight[];
@@ -237,6 +246,7 @@ class Global
static std::string asSky;
static bool bnewAirCouplers;
// Ra: nowe zmienne globalne
static float AnisotropicFiltering; // requested level of anisotropic filtering. TODO: move it to renderer object
static int iDefaultFiltering; // domyślne rozmywanie tekstur TGA
static int iBallastFiltering; // domyślne rozmywanie tekstury podsypki
static int iRailProFiltering; // domyślne rozmywanie tekstury szyn
@@ -250,8 +260,13 @@ class Global
static bool bOpenGL_1_5; // czy są dostępne funkcje OpenGL 1.5
*/
static double fLuminance; // jasność światła do automatycznego zapalania
static float SunAngle; // angle of the sun relative to horizon
static int iMultiplayer; // blokada działania niektórych eventów na rzecz kominikacji
static HWND hWnd; // uchwyt okna
static int ScreenWidth; // current window dimensions. TODO: move it to renderer
static int ScreenHeight;
static float ZoomFactor; // determines current camera zoom level. TODO: move it to the renderer
static float FieldOfView; // vertical field of view for the camera. TODO: move it to the renderer
static int iCameraLast;
static std::string asRelease; // numer
static std::string asVersion; // z opisem
@@ -346,6 +361,7 @@ class Global
static double fMWDph[2];
static double fMWDvolt[2];
static double fMWDamp[2];
static double fMWDlowVolt[2];
static int iMWDdivider;
};
//---------------------------------------------------------------------------

View File

@@ -23,7 +23,7 @@ http://mozilla.org/MPL/2.0/.
#include "Logs.h"
#include "usefull.h"
#include "Timer.h"
#include "Texture.h"
#include "renderer.h"
#include "Event.h"
#include "EvLaunch.h"
#include "TractionPower.h"
@@ -276,7 +276,7 @@ void TGroundNode::RaRenderVBO()
{ // renderowanie z domyslnego bufora VBO
glColor3ub(Diffuse[0], Diffuse[1], Diffuse[2]);
if (TextureID)
TextureManager.Bind(TextureID); // Ustaw aktywną teksturę
GfxRenderer.Bind(TextureID); // Ustaw aktywną teksturę
glDrawArrays(iType, iVboPtr, iNumVerts); // Narysuj naraz wszystkie trójkąty
}
@@ -327,9 +327,15 @@ void TGroundNode::RenderVBO()
if (linealpha > 255)
linealpha = 255;
float r, g, b;
r = floor(Diffuse[0] * Global::ambientDayLight[0]); // w zaleznosci od koloru swiatla
g = floor(Diffuse[1] * Global::ambientDayLight[1]);
b = floor(Diffuse[2] * Global::ambientDayLight[2]);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = floor( Diffuse[ 0 ] * Global::ambientDayLight[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::ambientDayLight[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::ambientDayLight[ 2 ] );
#else
r = floor( Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] );
#endif
glColor4ub(r, g, b, linealpha); // przezroczystosc dalekiej linii
// glDisable(GL_LIGHTING); //nie powinny świecić
glDrawArrays(iType, iVboPtr, iNumPts); // rysowanie linii
@@ -388,9 +394,15 @@ void TGroundNode::RenderAlphaVBO()
float linealpha = 255000 * fLineThickness / (mgn + 1.0);
if (linealpha > 255)
linealpha = 255;
r = Diffuse[0] * Global::ambientDayLight[0]; // w zaleznosci od koloru swiatla
g = Diffuse[1] * Global::ambientDayLight[1];
b = Diffuse[2] * Global::ambientDayLight[2];
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = Diffuse[ 0 ] * Global::ambientDayLight[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
#endif
glColor4ub(r, g, b, linealpha); // przezroczystosc dalekiej linii
// glDisable(GL_LIGHTING); //nie powinny świecić
glDrawArrays(iType, iVboPtr, iNumPts); // rysowanie linii
@@ -445,7 +457,7 @@ void TGroundNode::Compile(bool many)
#ifdef USE_VERTEX_ARRAYS
glVertexPointer(3, GL_DOUBLE, sizeof(vector3), &Points[0].x);
#endif
TextureManager.Bind(0);
GfxRenderer.Bind(0);
#ifdef USE_VERTEX_ARRAYS
glDrawArrays(iType, 0, iNumPts);
#else
@@ -466,7 +478,7 @@ void TGroundNode::Compile(bool many)
glTexCoordPointer(2, GL_FLOAT, sizeof(TGroundVertex), &tri->Vertices[0].tu);
#endif
glColor3ub(tri->Diffuse[0], tri->Diffuse[1], tri->Diffuse[2]);
TextureManager.Bind(Global::bWireFrame ? 0 : tri->TextureID);
GfxRenderer.Bind(Global::bWireFrame ? 0 : tri->TextureID);
#ifdef USE_VERTEX_ARRAYS
glDrawArrays(Global::bWireFrame ? GL_LINE_LOOP : tri->iType, 0, tri->iNumVerts);
#else
@@ -494,7 +506,7 @@ void TGroundNode::Compile(bool many)
else if (iType == TP_MESH)
{ // grupa ze wspólną teksturą - wrzucanie do wspólnego Display List
if (TextureID)
TextureManager.Bind(TextureID); // Ustaw aktywną teksturę
GfxRenderer.Bind(TextureID); // Ustaw aktywną teksturę
TGroundNode *n = nNode;
while (n ? n->TextureID == TextureID : false)
{ // wszystkie obiekty o tej samej testurze
@@ -555,7 +567,7 @@ void TGroundNode::RenderDL()
return smTerrain->RenderDL();
}
// if (pTriGroup) if (pTriGroup!=this) return; //wyświetla go inny obiekt
double mgn = SquareMagnitude(pCenter - Global::pCameraPosition);
double mgn = SquareMagnitude(pCenter - Global::pCameraPosition) / Global::ZoomFactor;
if ((mgn > fSquareRadius) || (mgn < fSquareMinRadius)) // McZapkie-070602: nie rysuj odleglych
// obiektow ale sprawdzaj wyzwalacz
// zdarzen
@@ -583,9 +595,15 @@ void TGroundNode::RenderDL()
// if (iNumPts)
{ // wszelkie linie są rysowane na samym końcu
float r, g, b;
r = Diffuse[0] * Global::ambientDayLight[0]; // w zaleznosci od koloru swiatla
g = Diffuse[1] * Global::ambientDayLight[1];
b = Diffuse[2] * Global::ambientDayLight[2];
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = Diffuse[ 0 ] * Global::ambientDayLight[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
#endif
glColor4ub(r, g, b, 1.0);
glCallList(DisplayListID);
// glColor4fv(Diffuse); //przywrócenie koloru
@@ -615,7 +633,7 @@ void TGroundNode::RenderAlphaDL()
// i jezeli tak to odpowiedni GL_GREATER w przeciwnym wypadku standardowy 0.04
// if (pTriGroup) if (pTriGroup!=this) return; //wyświetla go inny obiekt
double mgn = SquareMagnitude(pCenter - Global::pCameraPosition);
double mgn = SquareMagnitude(pCenter - Global::pCameraPosition) / Global::ZoomFactor;
float r, g, b;
if (mgn < fSquareMinRadius)
return;
@@ -659,9 +677,15 @@ void TGroundNode::RenderAlphaDL()
float linealpha = 255000 * fLineThickness / (mgn + 1.0);
if (linealpha > 255)
linealpha = 255;
r = Diffuse[0] * Global::ambientDayLight[0]; // w zaleznosci od koloru swiatla
g = Diffuse[1] * Global::ambientDayLight[1];
b = Diffuse[2] * Global::ambientDayLight[2];
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = Diffuse[ 0 ] * Global::ambientDayLight[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
#endif
glColor4ub(r, g, b, linealpha); // przezroczystosc dalekiej linii
glCallList(DisplayListID);
}
@@ -1817,29 +1841,20 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
case TP_DYNAMIC:
tmp->DynamicObject = new TDynamicObject();
// tmp->DynamicObject->Load(Parser);
parser->getTokens();
*parser >> token;
str1 = token; // katalog
// McZapkie: doszedl parametr ze zmienialna skora
parser->getTokens();
*parser >> token;
Skin = token; // tekstura wymienna
parser->getTokens();
*parser >> token;
str3 = token; // McZapkie-131102: model w MMD
parser->getTokens(3);
*parser
>> str1 // katalog
>> Skin // tekstura wymienna
>> str3; // McZapkie-131102: model w MMD
if (bTrainSet)
{ // jeśli pojazd jest umieszczony w składzie
str = asTrainSetTrack;
parser->getTokens();
*parser >> tf1; // Ra: -1 oznacza odwrotne wstawienie, normalnie w składzie 0
parser->getTokens();
*parser >> token;
DriverType = token; // McZapkie:010303 - w przyszlosci rozne
// konfiguracje mechanik/pomocnik itp
parser->getTokens(3);
*parser
>> tf1 // Ra: -1 oznacza odwrotne wstawienie, normalnie w składzie 0
>> DriverType // McZapkie:010303 - w przyszlosci rozne konfiguracje mechanik/pomocnik itp
>> str4;
tf3 = fTrainSetVel; // prędkość
parser->getTokens();
*parser >> token;
str4 = token;
int2 = str4.find("."); // yB: wykorzystuje tutaj zmienna, ktora potem bedzie ladunkiem
if (int2 != string::npos) // yB: jesli znalazl kropke, to ja przetwarza jako parametry
{
@@ -1868,17 +1883,12 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
fTrainSetDist = 0; // zerowanie dodatkowego przesunięcia
asTrainName = ""; // puste oznacza jazdę pojedynczego bez rozkładu, "none" jest dla
// składu (trainset)
parser->getTokens();
*parser >> token;
str = token; // track
parser->getTokens();
*parser >> tf1; // Ra: -1 oznacza odwrotne wstawienie
parser->getTokens();
*parser >> token;
DriverType = token; // McZapkie:010303: obsada
parser->getTokens();
*parser >>
tf3; // prędkość, niektórzy wpisują tu "3" jako sprzęg, żeby nie było tabliczki
parser->getTokens(4);
*parser
>> str // track
>> tf1 // Ra: -1 oznacza odwrotne wstawienie
>> DriverType // McZapkie:010303: obsada
>> tf3; // prędkość, niektórzy wpisują tu "3" jako sprzęg, żeby nie było tabliczki
iTrainSetWehicleNumber = 0;
TempConnectionType[iTrainSetWehicleNumber] = 3; // likwidacja tabliczki na końcu?
}
@@ -1887,8 +1897,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
if (int2 > 0)
{ // jeżeli ładunku jest więcej niż 0, to rozpoznajemy jego typ
parser->getTokens();
*parser >> token;
str2 = token; // LoadType
*parser >> str2; // LoadType
if (str2 == "enddynamic") // idiotoodporność: ładunek bez podanego typu
{
str2 = "";
@@ -1962,6 +1971,16 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
}
if (token.compare("enddynamic") != 0)
Error("enddynamic statement missing");
/*
if( tmp->DynamicObject->MoverParameters->LightPowerSource.SourceType != TPowerSource::NotDefined ) {
// if the vehicle has defined light source, it can (potentially) emit light, so add it to the light array
*/
if( tmp->DynamicObject->MoverParameters->SecuritySystem.SystemType != 0 ) {
// we check for presence of security system, as a way to determine whether the vehicle is a controllable engine
// NOTE: this isn't 100% precise, e.g. middle EZT module comes with security system, while it has no lights
m_lights.insert( tmp->DynamicObject );
}
break;
case TP_MODEL:
if (rmin < 0)
@@ -2109,8 +2128,8 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
tmp->PROBLEND = false;
}
#endif
tmp->TextureID = TextureManager.GetTextureId( str, szTexturePath );
tmp->iFlags = TextureManager.Texture(tmp->TextureID).has_alpha ? 0x220 : 0x210; // z usuwaniem
tmp->TextureID = GfxRenderer.GetTextureId( str, szTexturePath );
tmp->iFlags = GfxRenderer.Texture(tmp->TextureID).has_alpha ? 0x220 : 0x210; // z usuwaniem
if (((tmp->iType == GL_TRIANGLES) && (tmp->iFlags & 0x10)) ?
Global::pTerrainCompact->TerrainLoaded() :
false)
@@ -2454,15 +2473,20 @@ void TGround::FirstInit()
else
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO, TBD: re-implement this
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos); // daylight position
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight); // kolor wszechobceny
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight); // kolor padający
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight); // kolor odbity
// musi być tutaj, bo wcześniej nie mieliśmy wartości światła
#endif
/*
if (Global::fMoveLight >= 0.0) // albo tak, albo niech ustala minimum ciemności w nocy
{
*/
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO, TBD: re-implement this
Global::fLuminance = // obliczenie luminacji "światła w ciemności"
+0.150 * Global::ambientDayLight[0] // R
+ 0.295 * Global::ambientDayLight[1] // G
@@ -2472,6 +2496,7 @@ void TGround::FirstInit()
Global::ambientDayLight[i] *=
0.1 / Global::fLuminance; // ograniczenie jasności w nocy
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Global::ambientDayLight);
#endif
/*
}
else if (Global::bDoubleAmbient) // Ra: wcześniej było ambient dawane na obydwa światła
@@ -2837,6 +2862,7 @@ bool TGround::Init(std::string asFile, HDC hDC)
else if (str == "light")
{ // Ra: ustawianie światła przeniesione do FirstInit
WriteLog("Scenery light definition");
#ifdef EU07_USE_OLD_LIGHTING_MODEL
vector3 lp;
parser.getTokens();
parser >> lp.x;
@@ -2848,27 +2874,44 @@ bool TGround::Init(std::string asFile, HDC hDC)
Global::lightPos[0] = lp.x; // daylight position
Global::lightPos[1] = lp.y;
Global::lightPos[2] = lp.z;
parser.getTokens();
parser >> Global::ambientDayLight[0]; // kolor wszechobceny
parser.getTokens();
parser >> Global::ambientDayLight[1];
parser.getTokens();
parser >> Global::ambientDayLight[2];
parser.getTokens();
parser >> Global::diffuseDayLight[0]; // kolor padający
parser.getTokens();
parser >> Global::diffuseDayLight[1];
parser.getTokens();
parser >> Global::diffuseDayLight[2];
parser.getTokens();
parser >> Global::specularDayLight[0]; // kolor odbity
parser.getTokens();
parser >> Global::specularDayLight[1];
parser.getTokens();
parser >> Global::specularDayLight[2];
#else
parser.getTokens(3, false);
parser
>> Global::DayLight.direction.x
>> Global::DayLight.direction.y
>> Global::DayLight.direction.z;;
Global::DayLight.direction.Normalize();
#endif
parser.getTokens(9, false);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
parser
>> Global::ambientDayLight[ 0 ]
>> Global::ambientDayLight[ 1 ]
>> Global::ambientDayLight[ 2 ]
>> Global::diffuseDayLight[ 0 ]
>> Global::diffuseDayLight[ 1 ]
>> Global::diffuseDayLight[ 2 ]
>> Global::specularDayLight[ 0 ]
>> Global::specularDayLight[ 1 ]
>> Global::specularDayLight[ 2 ];
#else
/*
parser
// kolor wszechobceny
>> Global::DayLight.ambient[0]
>> Global::DayLight.ambient[1]
>> Global::DayLight.ambient[2]
// kolor padający
>> Global::DayLight.diffuse[0]
>> Global::DayLight.diffuse[1]
>> Global::DayLight.diffuse[2]
// kolor odbity
>> Global::DayLight.specular[0]
>> Global::DayLight.specular[1]
>> Global::DayLight.specular[2];
*/
#endif
do
{
parser.getTokens();
@@ -4510,6 +4553,25 @@ bool TGround::Update(double dt, int iter)
return true;
};
// updates scene lights array
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
bool TGround::GetTraction(TDynamicObject *model)
{ // aktualizacja drutu zasilającego dla każdego pantografu, żeby odczytać napięcie
@@ -4760,6 +4822,27 @@ bool TGround::GetTraction(TDynamicObject *model)
return true;
};
bool
TGround::Render( Math3D::vector3 const &Camera ) {
GfxRenderer.Update_Lights( m_lights );
if( Global::bUseVBO ) { // renderowanie przez VBO
if( !RenderVBO( Camera ) )
return false;
if( !RenderAlphaVBO( Camera ) )
return false;
}
else { // renderowanie przez Display List
if( !RenderDL( Camera ) )
return false;
if( !RenderAlphaDL( Camera ) )
return false;
}
return true;
}
bool TGround::RenderDL(vector3 pPosition)
{ // renderowanie scenerii z Display List - faza nieprzezroczystych
glDisable(GL_BLEND);
@@ -5291,6 +5374,8 @@ void TGround::DynamicRemove(TDynamicObject *dyn)
node = (*n); // zapamiętanie węzła, aby go usunąć
(*n) = node->nNext; // pominięcie na liście
Global::TrainDelete(d);
// remove potential entries in the light array
m_lights.remove( d );
d = d->Next(); // przejście do kolejnego pojazdu, póki jeszcze jest
delete node; // usuwanie fizyczne z pamięci
}

View File

@@ -16,7 +16,9 @@ http://mozilla.org/MPL/2.0/.
#include "ResourceManager.h"
#include "Texture.h"
#include "dumb3d.h"
#include "Float3d.h"
#include "Names.h"
#include "lightarray.h"
using namespace Math3D;
@@ -303,11 +305,11 @@ class TGround
TNames *sTracks = nullptr; // posortowane nazwy torów i eventów
#else
typedef std::unordered_map<std::string, TEvent *> event_map;
// typedef std::unordered_map<std::string, TGroundNode *> groundnode_map;
event_map m_eventmap;
// groundnode_map m_memcellmap, m_modelmap, m_trackmap;
TNames<TGroundNode *> m_trackmap;
#endif
light_array m_lights; // collection of dynamic light sources present in the scene
private: // metody prywatne
bool EventConditon(TEvent *e);
@@ -350,8 +352,10 @@ class TGround
void MoveGroundNode(vector3 pPosition);
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS
void Update_Lights(); // updates scene lights array
bool AddToQuery(TEvent *Event, TDynamicObject *Node);
bool GetTraction(TDynamicObject *model);
bool Render( Math3D::vector3 const &Camera );
bool RenderDL(vector3 pPosition);
bool RenderAlphaDL(vector3 pPosition);
bool RenderVBO(vector3 pPosition);

View File

@@ -19,7 +19,7 @@ http://mozilla.org/MPL/2.0/.
#include "logs.h"
#include "mczapkie/mctools.h"
#include "Usefull.h"
#include "Texture.h"
#include "renderer.h"
#include "Timer.h"
#include "mtable.h"
//---------------------------------------------------------------------------
@@ -219,6 +219,9 @@ template <typename ColorT> inline void readColor(cParser &parser, ColorT *color)
double discard;
parser.getTokens(4, false);
parser >> discard >> color[0] >> color[1] >> color[2];
color[ 0 ] /= 255.0;
color[ 1 ] /= 255.0;
color[ 2 ] /= 255.0;
};
inline void readColor(cParser &parser, int &color)
@@ -275,7 +278,8 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
if (dynamic)
{ // dla pojazdu, blokujemy załączone submodele, które mogą być
// nieobsługiwane
if (token.find("_on") + 3 == token.length()) // jeśli nazwa kończy się na "_on"
if ( (token.size() >= 3)
&& (token.find("_on") + 3 == token.length())) // jeśli nazwa kończy się na "_on"
iVisible = 0; // to domyślnie wyłączyć, żeby się nie nakładało z obiektem "_off"
}
else // dla pozostałych modeli blokujemy zapalone światła, które mogą być
@@ -411,12 +415,12 @@ int TSubModel::Load(cParser &parser, TModel3d *Model, int Pos, bool dynamic)
TextureNameSet(texture.c_str());
if (texture.find_first_of("/\\") == texture.npos)
texture.insert(0, Global::asCurrentTexturePath.c_str());
TextureID = TextureManager.GetTextureId( texture, szTexturePath );
TextureID = GfxRenderer.GetTextureId( texture, szTexturePath );
// TexAlpha=TTexturesManager::GetAlpha(TextureID);
// iFlags|=TexAlpha?0x20:0x10; //0x10-nieprzezroczysta, 0x20-przezroczysta
if (Opacity < 1.0) // przezroczystość z tekstury brana tylko dla Opacity
// 0!
iFlags |= TextureManager.Texture(TextureID).has_alpha ?
iFlags |= GfxRenderer.Texture(TextureID).has_alpha ?
0x20 :
0x10; // 0x10-nieprzezroczysta, 0x20-przezroczysta
else
@@ -636,7 +640,7 @@ int TSubModel::TriangleAdd(TModel3d *m, texture_manager::size_type tex, int tri)
m->AddTo(this, s);
}
// s->asTexture=AnsiString(TTexturesManager::GetName(tex).c_str());
s->TextureNameSet(TextureManager.Texture(tex).name.c_str());
s->TextureNameSet(GfxRenderer.Texture(tex).name.c_str());
s->TextureID = tex;
s->eType = GL_TRIANGLES;
// iAnimOwner=0; //roboczy wskaźnik na wierzchołek
@@ -714,7 +718,7 @@ void TSubModel::DisplayLists()
{
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
TextureManager.Bind(0);
GfxRenderer.Bind(0);
// if (eType==smt_FreeSpotLight)
// {
// if (iFarAttenDecay==0)
@@ -737,9 +741,9 @@ void TSubModel::DisplayLists()
{ // punkty świecące dookólnie
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
TextureManager.Bind(0); // tekstury nie ma
GfxRenderer.Bind(0); // tekstury nie ma
glColorMaterial(GL_FRONT, GL_EMISSION);
glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie blendowaly
// glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie blendowaly
glBegin(GL_POINTS);
for (int i = 0; i < iNumVerts; i++)
{
@@ -748,7 +752,7 @@ void TSubModel::DisplayLists()
glVertex3fv(&Vertices[i].Point.x);
};
glEnd();
glEnable(GL_LIGHTING);
// glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
glEndList();
@@ -813,10 +817,13 @@ void TSubModel::InitialRotate(bool doit)
Vertices[i].Point.y = Vertices[i].Point.z;
Vertices[i].Point.z = t;
// wektory normalne również trzeba przekształcić, bo się źle oświetlają
Vertices[i].Normal.x = -Vertices[i].Normal.x; // zmiana znaku X
t = Vertices[i].Normal.y; // zamiana Y i Z
Vertices[i].Normal.y = Vertices[i].Normal.z;
Vertices[i].Normal.z = t;
if( eType != TP_STARS ) {
// gwiazdki mają kolory zamiast normalnych, to // ich wtedy nie ruszamy
Vertices[ i ].Normal.x = -Vertices[ i ].Normal.x; // zmiana znaku X
t = Vertices[ i ].Normal.y; // zamiana Y i Z
Vertices[ i ].Normal.y = Vertices[ i ].Normal.z;
Vertices[ i ].Normal.z = t;
}
}
if (Child)
Child->InitialRotate(doit); // potomne ewentualnie obrócimy
@@ -1100,11 +1107,11 @@ void TSubModel::RenderDL()
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
TextureManager.Bind(ReplacableSkinId[-TextureID]);
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=!(iAlpha&1); //zmiana tylko w przypadku wymienej tekstury
}
else
TextureManager.Bind(TextureID); // również 0
GfxRenderer.Bind(TextureID); // również 0
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
@@ -1197,11 +1204,11 @@ void TSubModel::RenderAlphaDL()
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
TextureManager.Bind(ReplacableSkinId[-TextureID]);
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=iAlpha&1; //zmiana tylko w przypadku wymienej tekstury
}
else
TextureManager.Bind(TextureID); // również 0
GfxRenderer.Bind(TextureID); // również 0
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
@@ -1278,11 +1285,11 @@ void TSubModel::RenderVBO()
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
TextureManager.Bind(ReplacableSkinId[-TextureID]);
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=!(iAlpha&1); //zmiana tylko w przypadku wymienej tekstury
}
else
TextureManager.Bind(TextureID); // również 0
GfxRenderer.Bind(TextureID); // również 0
glColor3fv(f4Diffuse); // McZapkie-240702: zamiast ub
// glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,f4Diffuse); //to samo,
// co glColor
@@ -1349,7 +1356,7 @@ void TSubModel::RenderVBO()
Distdimm=1;
*/
TextureManager.Bind(0); // nie teksturować
GfxRenderer.Bind(0); // nie teksturować
// glColor3f(f4Diffuse[0],f4Diffuse[1],f4Diffuse[2]);
// glColorMaterial(GL_FRONT,GL_EMISSION);
float color[4] = {f4Diffuse[0] * Distdimm, f4Diffuse[1] * Distdimm,
@@ -1378,7 +1385,7 @@ void TSubModel::RenderVBO()
if (pRoot->StartColorVBO())
{ // wyświetlanie kolorowych punktów zamiast
// trójkątów
TextureManager.Bind(0); // tekstury nie ma
GfxRenderer.Bind(0); // tekstury nie ma
glColorMaterial(GL_FRONT, GL_EMISSION);
glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie
// blendowaly
@@ -1452,11 +1459,11 @@ void TSubModel::RenderAlphaVBO()
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skory
TextureManager.Bind(ReplacableSkinId[-TextureID]);
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=iAlpha&1; //zmiana tylko w przypadku wymienej tekstury
}
else
TextureManager.Bind(TextureID); // również 0
GfxRenderer.Bind(TextureID); // również 0
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
@@ -1624,14 +1631,14 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, float8 *v, TStringPack *t, TS
std::string tex = pTexture;
if (tex.find_last_of("/\\") == std::string::npos)
tex.insert(0, Global::asCurrentTexturePath);
TextureID = TextureManager.GetTextureId( tex, szTexturePath );
TextureID = GfxRenderer.GetTextureId( tex, szTexturePath );
// TexAlpha=TTexturesManager::GetAlpha(TextureID); //zmienna robocza
// ustawienie cyklu przezroczyste/nieprzezroczyste zależnie od własności
// stałej tekstury
// iFlags=(iFlags&~0x30)|(TTexturesManager::GetAlpha(TextureID)?0x20:0x10);
// //0x10-nieprzezroczysta, 0x20-przezroczysta
if (Opacity < 1.0) // przezroczystość z tekstury brana tylko dla Opacity 0!
iFlags |= TextureManager.Texture(TextureID).has_alpha ?
iFlags |= GfxRenderer.Texture(TextureID).has_alpha ?
0x20 :
0x10; // 0x10-nieprzezroczysta, 0x20-przezroczysta
else
@@ -1805,7 +1812,8 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
// wczytanie modelu z pliku
std::string name = ToLower(FileName);
// trim extension if needed
if (name.substr(name.rfind('.')) == ".t3d")
if( ( name.rfind( '.' ) != std::string::npos )
&& ( name.substr( name.rfind( '.' ) ) == ".t3d" ) )
{
name.erase(name.rfind('.'));
}

View File

@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "PyInt.h"
#include "renderer.h"
#include "Train.h"
#include "Logs.h"
//#include <process.h>
@@ -453,7 +454,7 @@ void TPythonScreens::init(cParser &parser, TModel3d *model, std::string const &n
WriteLog( "Python Screen: submodel " + subModelName + " not found - Ignoring screen" );
return; // nie ma takiego sub modelu w danej kabinie pomijamy
}
int textureId = TextureManager.Texture(subModel->GetTextureId()).id;
int textureId = GfxRenderer.Texture(subModel->GetTextureId()).id;
if (textureId <= 0)
{
WriteLog( "Python Screen: invalid texture id " + std::to_string(textureId) + " - Ignoring screen" );

View File

@@ -21,6 +21,11 @@ http://mozilla.org/MPL/2.0/.
// 101206 Ra: trapezoidalne drogi
// 110806 Ra: odwrócone mapowanie wzdłuż - Point1 == 1.0
float Interpolate( float const First, float const Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
std::string Where(vector3 p)
{ // zamiana współrzędnych na tekst, używana w błędach
return std::to_string(p.x) + " " + std::to_string(p.y) + " " + std::to_string(p.z);
@@ -116,7 +121,11 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
fStoop = atan2((Point2.y - Point1.y),
fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
SafeDeleteArray(fTsBuffer);
/*
if ((bCurve) && (fStep > 0))
*/
// we're enforcing sub-division of even straight track, to have dense enough mesh for the spotlight to work with
if( fStep > 0 )
{ // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
double s = 0;
int i = 0;
@@ -454,6 +463,7 @@ void TSegment::RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, doubl
}
}
else
#ifdef EU07_USE_OLD_LIGHTING_MODEL
{ // gdy prosty, nie modyfikujemy wektora kierunkowego i poprzecznego
pos1 = FastGetPoint((fStep * iSkip) / fLength);
pos2 = FastGetPoint_1();
@@ -498,6 +508,91 @@ void TSegment::RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, doubl
}
glEnd();
}
#else
{
Math3D::vector3 const pos0 = FastGetPoint( ( fStep * iSkip ) / fLength );
Math3D::vector3 const pos1 = FastGetPoint_1();
dir = GetDirection();
Math3D::vector3 const parallel = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
Math3D::vector3 startnormal0, startnormal1, endnormal0, endnormal1;
Math3D::vector3 startvertex0, startvertex1, endvertex0, endvertex1;
float startuv0, startuv1, enduv0, enduv1;
for( j = 0; j < iNumShapePoints - 1; ++j ) {
startnormal0 = ShapePoints[ j ].n.x * parallel;
startnormal0.y += ShapePoints[ j ].n.y;
startvertex0 = parallel * ShapePoints[ j ].x + pos0;
startvertex0.y += ShapePoints[ j ].y;
startuv0 = ShapePoints[ j ].z;
startnormal1 = ShapePoints[ j + 1 ].n.x * parallel;
startnormal1.y += ShapePoints[ j + 1 ].n.y;
startvertex1 = parallel * ShapePoints[ j + 1 ].x + pos0;
startvertex1.y += ShapePoints[ j + 1 ].y;
startuv1 = ShapePoints[ j + 1 ].z;
if( trapez == false ) {
// single profile throughout
endnormal0 = startnormal0;
endvertex0 = startvertex0 + ( pos1 - pos0 );
enduv0 = startuv0;
endnormal1 = startnormal1;
endvertex1 = startvertex1 + ( pos1 - pos0 );
enduv1 = startuv1;
}
else {
// end profile is different
endnormal0 = ShapePoints[ j + iNumShapePoints ].n.x * parallel;
endnormal0.y += ShapePoints[ j + iNumShapePoints ].n.y;
endvertex0 = parallel * ShapePoints[ j + iNumShapePoints ].x + pos1; // odsunięcie
endvertex0.y += ShapePoints[ j + iNumShapePoints ].y; // wysokość
enduv0 = ShapePoints[ j + iNumShapePoints ].z;
endnormal1 = ShapePoints[ j + iNumShapePoints + 1 ].n.x * parallel;
endnormal1.y += ShapePoints[ j + iNumShapePoints + 1 ].n.y;
endvertex1 = parallel * ShapePoints[ j + iNumShapePoints + 1 ].x + pos1; // odsunięcie
endvertex1.y += ShapePoints[ j + iNumShapePoints + 1 ].y; // wysokość
enduv1 = ShapePoints[ j + iNumShapePoints + 1 ].z;
}
// now build strips, lerping from start to endpoint
step = 10.0; // arbitrary segment size for straights
float s = 0.0,
t = 0.0,
uv = 0.0;
glBegin( GL_TRIANGLE_STRIP );
while( s < fLength ) {
t = s / fLength;
uv = s / fTextureLength;
auto const normal1lerp = Interpolate( startnormal1, endnormal1, t );
glNormal3dv( &normal1lerp.x );
auto const uv1lerp = Interpolate( startuv1, enduv1, t );
glTexCoord2f( uv1lerp, uv );
auto const vertex1lerp = Interpolate( startvertex1, endvertex1, t );
glVertex3dv( &vertex1lerp.x );
auto const normal0lerp = Interpolate( startnormal0, endnormal0, t );
glNormal3dv( &normal0lerp.x );
auto const uv0lerp = Interpolate( startuv0, enduv0, t );
glTexCoord2f( uv0lerp, uv );
auto const vertex0lerp = Interpolate( startvertex0, endvertex0, t );
glVertex3dv( &vertex0lerp.x );
s += step;
}
// add ending vertex pair if needed
glNormal3dv( &endnormal1.x );
glTexCoord2f( enduv1, fLength / fTextureLength );
glVertex3dv( &endvertex1.x );
glNormal3dv( &endnormal0.x );
glTexCoord2f( enduv0, fLength / fTextureLength );
glVertex3dv( &endvertex0.x );
glEnd();
}
}
#endif
};
void TSegment::RenderSwitchRail(const vector6 *ShapePoints1, const vector6 *ShapePoints2,
@@ -641,7 +736,7 @@ void TSegment::RenderSwitchRail(const vector6 *ShapePoints1, const vector6 *Shap
void TSegment::Render()
{
vector3 pt;
TextureManager.Bind(0);
GfxRenderer.Bind(0);
int i;
if (bCurve)
{

View File

@@ -14,19 +14,14 @@ http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "Texture.h"
#include "texture.h"
#include <ddraw.h>
#include <io.h>
#include <fcntl.h>
#include "opengl/glew.h"
#include "Globals.h"
#include "usefull.h"
#include "globals.h"
#include "logs.h"
#include "Usefull.h"
#include "TextureDDS.h"
texture_manager TextureManager;
texture_manager::texture_manager() {
@@ -505,6 +500,11 @@ opengl_texture::set_filtering() {
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
if( GLEW_EXT_texture_filter_anisotropic ) {
// anisotropic filtering
::glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, Global::AnisotropicFiltering );
}
bool sharpen{ false };
for( auto const &trait : traits ) {

View File

@@ -97,5 +97,3 @@ private:
index_map m_texturemappings;
size_type m_activetexture{ 0 }; // last i.e. currently bound texture
};
extern texture_manager TextureManager;

View File

@@ -17,7 +17,7 @@ http://mozilla.org/MPL/2.0/.
#include "Globals.h"
#include "Logs.h"
#include "Usefull.h"
#include "Texture.h"
#include "renderer.h"
#include "Timer.h"
#include "Ground.h"
#include "parser.h"
@@ -508,7 +508,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
parser->getTokens();
*parser >> token;
str = token; // railtex
TextureID1 = (str == "none" ? 0 : TextureManager.GetTextureId(
TextureID1 = (str == "none" ? 0 : GfxRenderer.GetTextureId(
str, szTexturePath,
(iCategoryFlag & 1) ? Global::iRailProFiltering :
Global::iBallastFiltering));
@@ -519,7 +519,7 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
parser->getTokens();
*parser >> token;
str = token; // sub || railtex
TextureID2 = (str == "none" ? 0 : TextureManager.GetTextureId(
TextureID2 = (str == "none" ? 0 : GfxRenderer.GetTextureId(
str, szTexturePath,
(eType == tt_Normal) ? Global::iBallastFiltering :
Global::iRailProFiltering));
@@ -579,12 +579,12 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
if (TextureID1 && fTexLength)
{ // dla drogi trzeba ustalić proporcje boków nawierzchni
float w, h;
TextureManager.Bind(TextureID1);
GfxRenderer.Bind(TextureID1);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
if (h != 0.0)
fTexRatio1 = w / h; // proporcja boków
TextureManager.Bind(TextureID2);
GfxRenderer.Bind(TextureID2);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
if (h != 0.0)
@@ -1299,14 +1299,14 @@ void TTrack::Compile(GLuint tex)
}
}
if (!tex)
TextureManager.Bind( TextureID2 );
GfxRenderer.Bind( TextureID2 );
Segment->RenderLoft(bpts1, iTrapezoid ? -4 : 4, fTexLength);
}
if (TextureID1)
if (tex ? TextureID1 == tex : true) // jeśli pasuje do grupy (tex)
{ // szyny
if (!tex)
TextureManager.Bind( TextureID1 );
GfxRenderer.Bind( TextureID1 );
Segment->RenderLoft(rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft(rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
}
@@ -1345,7 +1345,7 @@ void TTrack::Compile(GLuint tex)
// McZapkie-130302 - poprawione rysowanie szyn
if (SwitchExtension->RightSwitch)
{ // zwrotnica prawa
TextureManager.Bind( TextureID1 );
GfxRenderer.Bind( TextureID1 );
SwitchExtension->Segments[0]->RenderLoft(rpts1, nnumPts, fTexLength,
2); // prawa szyna za iglicą
SwitchExtension->Segments[0]->RenderSwitchRail(
@@ -1354,7 +1354,7 @@ void TTrack::Compile(GLuint tex)
SwitchExtension->Segments[0]->RenderLoft(
rpts2, nnumPts, fTexLength); // lewa szyna normalnie cała
if (TextureID2 != TextureID1) // nie wiadomo, czy OpenGL to optymalizuje
TextureManager.Bind( TextureID2 );
GfxRenderer.Bind( TextureID2 );
SwitchExtension->Segments[1]->RenderLoft(
rpts1, nnumPts, fTexLength); // prawa szyna normalna cała
SwitchExtension->Segments[1]->RenderLoft(rpts2, nnumPts, fTexLength,
@@ -1365,7 +1365,7 @@ void TTrack::Compile(GLuint tex)
}
else
{ // lewa kiedyś działała lepiej niż prawa
TextureManager.Bind( TextureID1 );
GfxRenderer.Bind( TextureID1 );
SwitchExtension->Segments[0]->RenderLoft(
rpts1, nnumPts, fTexLength); // prawa szyna normalna cała
SwitchExtension->Segments[0]->RenderLoft(rpts2, nnumPts, fTexLength,
@@ -1374,7 +1374,7 @@ void TTrack::Compile(GLuint tex)
rpts2, rpts4, nnumPts, fTexLength, 2,
-SwitchExtension->fOffset2); // lewa iglica
if (TextureID2 != TextureID1) // nie wiadomo, czy OpenGL to optymalizuje
TextureManager.Bind( TextureID2 );
GfxRenderer.Bind( TextureID2 );
SwitchExtension->Segments[1]->RenderLoft(rpts1, nnumPts, fTexLength,
2); // prawa szyna za iglicą
SwitchExtension->Segments[1]->RenderSwitchRail(
@@ -1422,7 +1422,7 @@ void TTrack::Compile(GLuint tex)
if (tex ? TextureID1 == tex : true) // jeśli pasuje do grupy (tex)
{ // tworzenie trójkątów nawierzchni szosy
if (!tex)
TextureManager.Bind( TextureID1 );
GfxRenderer.Bind( TextureID1 );
Segment->RenderLoft(bpts1, iTrapezoid ? -2 : 2, fTexLength);
}
if (TextureID2)
@@ -1430,7 +1430,7 @@ void TTrack::Compile(GLuint tex)
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak
// w Midtown Madness 2?)
if (!tex)
TextureManager.Bind( TextureID2 );
GfxRenderer.Bind( TextureID2 );
vector6 rpts1[6],
rpts2[6]; // współrzędne przekroju i mapowania dla prawej i lewej strony
if (fTexHeight1 >= 0.0)
@@ -1610,7 +1610,7 @@ void TTrack::Compile(GLuint tex)
// Midtown Madness 2?)
if (TextureID2)
if (!tex)
TextureManager.Bind( TextureID2 );
GfxRenderer.Bind( TextureID2 );
vector6 rpts1[6],
rpts2[6]; // współrzędne przekroju i mapowania dla prawej i lewej strony
// Ra 2014-07: trzeba to przerobić na pętlę i pobierać profile (przynajmniej 2..4) z
@@ -1755,7 +1755,7 @@ void TTrack::Compile(GLuint tex)
if (tex ? TextureID1 == tex : true) // jeśli pasuje do grupy (tex)
{
if (!tex)
TextureManager.Bind( TextureID1 );
GfxRenderer.Bind( TextureID1 );
glBegin(GL_TRIANGLE_FAN); // takie kółeczko będzie
glNormal3f(0, 1, 0);
glTexCoord2f(0.5, 0.5); //środek tekstury na środku skrzyżowania
@@ -1787,7 +1787,7 @@ void TTrack::Compile(GLuint tex)
if (tex ? TextureID1 == tex : true) // jeśli pasuje do grupy (tex)
{
if (!tex)
TextureManager.Bind( TextureID1 );
GfxRenderer.Bind( TextureID1 );
Segment->RenderLoft(bpts1, numPts, fTexLength);
}
if (TextureID2)
@@ -1799,7 +1799,7 @@ void TTrack::Compile(GLuint tex)
vector6 rpts2[3] = {vector6(-fHTW, 0.0, 1.0), vector6(-fHTW - side, 0.0, 0.5),
vector6(-rozp, -fTexHeight1, 0.0)}; // Ra: po kiego 0.1?
if (!tex)
TextureManager.Bind( TextureID2 ); // brzeg rzeki
GfxRenderer.Bind( TextureID2 ); // brzeg rzeki
Segment->RenderLoft(rpts1, 3, fTexLength);
Segment->RenderLoft(rpts2, 3, fTexLength);
}
@@ -2473,7 +2473,7 @@ void TTrack::RaRenderVBO(int iPtr)
if (TextureID1)
if ((seg = SwitchExtension->Segments[0]->RaSegCount()) > 0)
{
TextureManager.Bind( TextureID1 ); // szyny +
GfxRenderer.Bind( TextureID1 ); // szyny +
for (i = 0; i < seg; ++i)
glDrawArrays(GL_TRIANGLE_STRIP, iPtr + 24 * i, 24);
iPtr += 24 * seg; // pominięcie lewej szyny
@@ -2484,7 +2484,7 @@ void TTrack::RaRenderVBO(int iPtr)
if (TextureID2)
if ((seg = SwitchExtension->Segments[1]->RaSegCount()) > 0)
{
TextureManager.Bind( TextureID2 ); // szyny -
GfxRenderer.Bind( TextureID2 ); // szyny -
for (i = 0; i < seg; ++i)
glDrawArrays(GL_TRIANGLE_STRIP, iPtr + 24 * i, 24);
iPtr += 24 * seg; // pominięcie lewej szyny
@@ -2498,14 +2498,14 @@ void TTrack::RaRenderVBO(int iPtr)
{
if (TextureID2)
{
TextureManager.Bind( TextureID2 ); // podsypka
GfxRenderer.Bind( TextureID2 ); // podsypka
for (i = 0; i < seg; ++i)
glDrawArrays(GL_TRIANGLE_STRIP, iPtr + 8 * i, 8);
iPtr += 8 * seg; // pominięcie podsypki
}
if (TextureID1)
{
TextureManager.Bind( TextureID1 ); // szyny
GfxRenderer.Bind( TextureID1 ); // szyny
for (i = 0; i < seg; ++i)
glDrawArrays(GL_TRIANGLE_STRIP, iPtr + 24 * i, 24);
iPtr += 24 * seg; // pominięcie lewej szyny
@@ -2520,7 +2520,7 @@ void TTrack::RaRenderVBO(int iPtr)
{
if (TextureID1)
{
TextureManager.Bind( TextureID1 ); // nawierzchnia
GfxRenderer.Bind( TextureID1 ); // nawierzchnia
for (i = 0; i < seg; ++i)
{
glDrawArrays(GL_TRIANGLE_STRIP, iPtr, 4);
@@ -2529,7 +2529,7 @@ void TTrack::RaRenderVBO(int iPtr)
}
if (TextureID2)
{
TextureManager.Bind( TextureID2 ); // pobocze
GfxRenderer.Bind( TextureID2 ); // pobocze
if (fTexHeight1 >= 0.0)
{ // normalna droga z poboczem
for (i = 0; i < seg; ++i)
@@ -2558,7 +2558,7 @@ void TTrack::RaRenderVBO(int iPtr)
{
if (TextureID1)
{
TextureManager.Bind( TextureID1 ); // nawierzchnia
GfxRenderer.Bind( TextureID1 ); // nawierzchnia
for (i = 0; i < seg; ++i)
{
glDrawArrays(GL_TRIANGLE_STRIP, iPtr, 4);
@@ -2567,7 +2567,7 @@ void TTrack::RaRenderVBO(int iPtr)
}
if (TextureID2)
{
TextureManager.Bind( TextureID2 ); // pobocze
GfxRenderer.Bind( TextureID2 ); // pobocze
for (i = 0; i < seg; ++i)
glDrawArrays(GL_TRIANGLE_STRIP, iPtr + 6 * i, 6);
iPtr += 6 * seg; // pominięcie lewego pobocza
@@ -2583,6 +2583,8 @@ void TTrack::RaRenderVBO(int iPtr)
void TTrack::EnvironmentSet()
{ // ustawienie zmienionego światła
glColor3f(1.0f, 1.0f, 1.0f); // Ra: potrzebne to?
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
if (eEnvironment)
{ // McZapkie-310702: zmiana oswietlenia w tunelu, wykopie
GLfloat ambientLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
@@ -2614,10 +2616,13 @@ void TTrack::EnvironmentSet()
break;
}
}
#endif
};
void TTrack::EnvironmentReset()
{ // przywrócenie domyślnego światła
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
switch (eEnvironment)
{ // przywrócenie globalnych ustawień światła, o ile było zmienione
case e_canyon: // wykop
@@ -2626,6 +2631,7 @@ void TTrack::EnvironmentReset()
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
}
#endif
};
void TTrack::RenderDyn()

View File

@@ -18,7 +18,7 @@ http://mozilla.org/MPL/2.0/.
#include "logs.h"
#include "mctools.h"
#include "TractionPower.h"
#include "Texture.h"
#include "renderer.h"
//---------------------------------------------------------------------------
/*
@@ -116,7 +116,7 @@ void TTraction::Optimize()
uiDisplayList = glGenLists(1);
glNewList(uiDisplayList, GL_COMPILE);
TextureManager.Bind(0);
GfxRenderer.Bind(0);
// glColor3ub(0,0,0); McZapkie: to do render
// glPushMatrix();
@@ -323,9 +323,15 @@ void TTraction::RenderDL(float mgn) // McZapkie: mgn to odleglosc od obserwatora
g *= 0.6;
b *= 0.6;
}
r *= Global::ambientDayLight[0]; // w zaleźności od koloru swiatła
g *= Global::ambientDayLight[1];
b *= Global::ambientDayLight[2];
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r *= Global::ambientDayLight[ 0 ]; // w zaleźności od koloru swiatła
g *= Global::ambientDayLight[ 1 ];
b *= Global::ambientDayLight[ 2 ];
#else
r *= Global::DayLight.ambient[ 0 ]; // w zaleźności od koloru swiatła
g *= Global::DayLight.ambient[ 1 ];
b *= Global::DayLight.ambient[2];
#endif
if (linealpha > 1.0)
linealpha = 1.0; // trzeba ograniczyć do <=1
glColor4f(r, g, b, linealpha);
@@ -463,7 +469,7 @@ void TTraction::RenderVBO(float mgn, int iPtr)
{ // renderowanie z użyciem VBO
if (Wires != 0 && !TestFlag(DamageFlag, 128)) // rysuj jesli sa druty i nie zerwana
{
TextureManager.Bind(0);
GfxRenderer.Bind(0);
glDisable(GL_LIGHTING); // aby nie używało wektorów normalnych do kolorowania
glColor4f(0, 0, 0, 1); // jak nieznany kolor to czarne nieprzezroczyste
if (!Global::bSmoothTraction)
@@ -527,9 +533,15 @@ void TTraction::RenderVBO(float mgn, int iPtr)
b = 0.0;
break; //żółte z podłączonym zasilaniem z obu stron
}
r = r * Global::ambientDayLight[0]; // w zaleznosci od koloru swiatla
g = g * Global::ambientDayLight[1];
b = b * Global::ambientDayLight[2];
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r *= Global::ambientDayLight[ 0 ]; // w zaleźności od koloru swiatła
g *= Global::ambientDayLight[ 1 ];
b *= Global::ambientDayLight[ 2 ];
#else
r *= Global::DayLight.ambient[ 0 ]; // w zaleźności od koloru swiatła
g *= Global::DayLight.ambient[ 1 ];
b *= Global::DayLight.ambient[ 2 ];
#endif
if (linealpha > 1.0)
linealpha = 1.0; // trzeba ograniczyć do <=1
glColor4f(r, g, b, linealpha);

View File

@@ -2832,6 +2832,20 @@ bool TTrain::Update( double const Deltatime )
/// napędu
}
if (Global::bMWDmasterEnable) // pobieranie danych dla pulpitu port (COM)
{
Console::ValueSet(0, mvOccupied->Compressor); // zbiornik główny
Console::ValueSet(1, mvOccupied->PipePress); // przewód główny
Console::ValueSet(2, mvOccupied->BrakePress); // cylinder hamulcowy
Console::ValueSet(3, fHVoltage); // woltomierz wysokiego napięcia
Console::ValueSet(4, fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1]);
// pierwszy amperomierz; dla EZT prąd całkowity
Console::ValueSet(5, fHCurrent[2]); // drugi amperomierz 2
Console::ValueSet(6, fHCurrent[3]); // drugi amperomierz 3
Console::ValueSet(7, fTachoVelocity);
//Console::ValueSet(8, mvControlled->BatteryVoltage); // jeszcze nie pora ;)
}
// hunter-080812: wyrzucanie szybkiego na elektrykach gdy nie ma napiecia
// przy dowolnym ustawieniu kierunkowego
// Ra: to już jest w T_MoverParameters::TractionForce(), ale zależy od
@@ -3752,12 +3766,21 @@ bool TTrain::Update( double const Deltatime )
false) // nie blokujemy AI
{ // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba
// Firleju: dlatego kasujemy i zastepujemy funkcją w Console
if (((mvOccupied->BrakeHandle == FV4a) ||
(mvOccupied->BrakeHandle == FVel6))) // może można usunąć ograniczenie do FV4a i FVel6?
if (mvOccupied->BrakeHandle == FV4a)
{
double b = Console::AnalogCalibrateGet(0);
b = b * 8 - 2;
b = Global::CutValueToRange(-2.0, b, mvOccupied->BrakeCtrlPosNo); // przycięcie zmiennej do granic
if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FV4a break position = " + to_string(b));
ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia
mvOccupied->BrakeLevelSet(b);
}
if (mvOccupied->BrakeHandle == FVel6) // może można usunąć ograniczenie do FV4a i FVel6?
{
double b = Console::AnalogCalibrateGet(0);
b = b * 7 - 1;
b = Global::CutValueToRange(-1.0, b, mvOccupied->BrakeCtrlPosNo); // przycięcie zmiennej do granic
if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FVel6 break position = " + to_string(b));
ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia
mvOccupied->BrakeLevelSet(b);
}
@@ -3768,19 +3791,23 @@ bool TTrain::Update( double const Deltatime )
// ggBrakeCtrl.UpdateValue(double(mvOccupied->BrakeCtrlPos));
ggBrakeCtrl.UpdateValue(mvOccupied->fBrakeCtrlPos);
ggBrakeCtrl.Update();
}
if (ggLocalBrake.SubModel)
{
if (DynamicObject->Mechanik ?
(DynamicObject->Mechanik->AIControllFlag ? false : (Global::iFeedbackMode == 4 || Global::bMWDmasterEnable)) :
(DynamicObject->Mechanik->AIControllFlag ? false : (Global::iFeedbackMode == 4 || (Global::bMWDmasterEnable && Global::bMWDBreakEnable))) :
false) // nie blokujemy AI
{ // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba
// Firleju: dlatego kasujemy i zastepujemy funkcją w Console
if ((mvOccupied->BrakeLocHandle == FD1))
{
double b = Console::AnalogCalibrateGet(1);
b *= 10;
b = Global::CutValueToRange(0.0, b, LocalBrakePosNo); // przycięcie zmiennej do granic
ggLocalBrake.UpdateValue(b); // przesów bez zaokrąglenia
if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FD1 break position = " + to_string(b));
mvOccupied->LocalBrakePos =
int(1.09 * b); // sposób zaokrąglania jest do ustalenia
}
@@ -4671,7 +4698,7 @@ bool TTrain::Update( double const Deltatime )
if ((!Console::Pressed(Global::Keys[k_DecBrakeLevel])) &&
(!Console::Pressed(Global::Keys[k_WaveBrake])) && (mvOccupied->BrakeCtrlPos == -1) &&
(mvOccupied->BrakeHandle == FVel6) && (DynamicObject->Controller != AIdriver) &&
(Global::iFeedbackMode != 4))
(Global::iFeedbackMode != 4) && (!(Global::bMWDmasterEnable && Global::bMWDBreakEnable)))
{
// mvOccupied->BrakeCtrlPos=(mvOccupied->BrakeCtrlPos)+1;
// mvOccupied->IncBrakeLevel();
@@ -5001,6 +5028,40 @@ bool TTrain::Update( double const Deltatime )
btHaslerBrakes.Turn(DynamicObject->MoverParameters->BrakePress > 0.4); // ciśnienie w cylindrach
btHaslerCurrent.Turn(DynamicObject->MoverParameters->Im != 0.0); // prąd na silnikach
// calculate current level of interior illumination
// TODO: organize it along with rest of train update in a more sensible arrangement
switch( iCabLightFlag ) // Ra: uzeleżnic od napięcia w obwodzie sterowania
{ // hunter-091012: uzaleznienie jasnosci od przetwornicy
case 0: {
//światło wewnętrzne zgaszone
DynamicObject->InteriorLightLevel = 0.0f;
break;
}
case 1: {
//światło wewnętrzne przygaszone (255 216 176)
if( mvOccupied->ConverterFlag == true ) {
// jasnosc dla zalaczonej przetwornicy
DynamicObject->InteriorLightLevel = 0.75f;
}
else {
DynamicObject->InteriorLightLevel = 0.375f;
}
break;
}
case 2: {
//światło wewnętrzne zapalone (255 216 176)
if( mvOccupied->ConverterFlag ==
true ) // jasnosc dla zalaczonej przetwornicy
{
DynamicObject->InteriorLightLevel = 1.0f;
}
else {
DynamicObject->InteriorLightLevel = 0.5f;
}
break;
}
}
m_updated = true;
return true; //(DynamicObject->Update(dt));
} // koniec update

561
World.cpp
View File

@@ -21,7 +21,7 @@ http://mozilla.org/MPL/2.0/.
#include "Globals.h"
#include "Logs.h"
#include "MdlMngr.h"
#include "Texture.h"
#include "renderer.h"
#include "Timer.h"
#include "mtable.h"
#include "Sound.h"
@@ -31,6 +31,7 @@ http://mozilla.org/MPL/2.0/.
#include "Train.h"
#include "Driver.h"
#include "Console.h"
#include "color.h"
#define TEXTURE_FILTER_CONTROL_EXT 0x8500
#define TEXTURE_LOD_BIAS_EXT 0x8501
@@ -263,93 +264,36 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Max texture size: " + std::to_string(Global::iMaxTextureSize));
}
/*-----------------------Render Initialization----------------------*/
if (Global::fOpenGL >= 1.2) // poniższe nie działa w 1.1
glTexEnvf(TEXTURE_FILTER_CONTROL_EXT, TEXTURE_LOD_BIAS_EXT, -1);
GLfloat FogColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear screen and depth buffer
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// WriteLog("glClearColor (FogColor[0], FogColor[1], FogColor[2], 0.0); ");
// glClearColor (1.0, 0.0, 0.0, 0.0); // Background Color
// glClearColor (FogColor[0], FogColor[1], FogColor[2], 0.0);
// Background // Color
glClearColor(Global::Background[0], Global::Background[1], Global::Background[2], 1.0); // Background Color
WriteLog("glFogfv(GL_FOG_COLOR, FogColor);");
glFogfv(GL_FOG_COLOR, FogColor); // Set Fog Color
glClearDepth( 1.0f ); // ZBuffer Value
glClearColor( 51.0f / 255.0f, 106.0f / 255.0f, 85.0f / 255.0f, 1.0f ); // Background Color
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Clear screen and depth buffer
WriteLog("glClearDepth(1.0f); ");
glClearDepth(1.0f); // ZBuffer Value
// glEnable(GL_NORMALIZE);
// glEnable(GL_RESCALE_NORMAL);
// glEnable(GL_CULL_FACE);
WriteLog("glEnable(GL_TEXTURE_2D);");
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
WriteLog("glShadeModel(GL_SMOOTH);");
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
WriteLog("glEnable(GL_DEPTH_TEST);");
glEnable(GL_DEPTH_TEST);
// McZapkie:261102-uruchomienie polprzezroczystosci (na razie linie) pod kierunkiem Marcina
// if (Global::bRenderAlpha) //Ra: wywalam tę flagę
{
WriteLog("glEnable(GL_BLEND);");
glEnable(GL_BLEND);
WriteLog("glEnable(GL_ALPHA_TEST);");
glEnable(GL_ALPHA_TEST);
WriteLog("glAlphaFunc(GL_GREATER,0.04);");
glAlphaFunc(GL_GREATER, 0.04);
WriteLog("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
WriteLog("glDepthFunc(GL_LEQUAL);");
glDepthFunc(GL_LEQUAL);
}
/*
else
{
WriteLog("glEnable(GL_ALPHA_TEST);");
glEnable(GL_ALPHA_TEST);
WriteLog("glAlphaFunc(GL_GREATER,0.5);");
glAlphaFunc(GL_GREATER,0.5);
WriteLog("glDepthFunc(GL_LEQUAL);");
glDepthFunc(GL_LEQUAL);
WriteLog("glDisable(GL_BLEND);");
glDisable(GL_BLEND);
}
*/
/* zakomentowanie to co bylo kiedys mieszane
WriteLog("glEnable(GL_ALPHA_TEST);");
glEnable(GL_ALPHA_TEST);//glGetIntegerv()
WriteLog("glAlphaFunc(GL_GREATER,0.5);");
// glAlphaFunc(GL_LESS,0.5);
glAlphaFunc(GL_GREATER,0.5);
// glBlendFunc(GL_SRC_ALPHA,GL_ONE);
WriteLog("glDepthFunc(GL_LEQUAL);");
glDepthFunc(GL_LEQUAL);//EQUAL);
// The Type Of Depth Testing To Do
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
*/
WriteLog("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);");
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
WriteLog("glPolygonMode(GL_FRONT, GL_FILL);");
glPolygonMode(GL_FRONT, GL_FILL);
WriteLog("glFrontFace(GL_CCW);");
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
WriteLog("glEnable(GL_CULL_FACE); ");
glEnable(GL_CULL_FACE); // Cull back-facing triangles
WriteLog("glLineWidth(1.0f);");
glLineWidth(1.0f);
// glLineWidth(2.0f);
WriteLog("glPointSize(3.0f);");
glPointSize(3.0f);
// glHint( GL_POINT_SMOOTH_HINT, GL_NICEST ); // Really Nice Perspective Calculations
// glEnable( GL_POINT_SMOOTH );
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// ----------- LIGHTING SETUP -----------
// Light values and coordinates
@@ -361,7 +305,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
Global::lightPos[3] = 0.0f;
// Ra: światła by sensowniej było ustawiać po wczytaniu scenerii
// TODO: re-implement this
// Ra: szczątkowe światło rozproszone - żeby było cokolwiek widać w ciemności
WriteLog("glLightModelfv(GL_LIGHT_MODEL_AMBIENT,darkLight);");
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Global::darkLight);
@@ -377,41 +321,20 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos);
WriteLog("glEnable(GL_LIGHT0);");
glEnable(GL_LIGHT0);
#endif
// glColor() ma zmieniać kolor wybrany w glColorMaterial()
WriteLog("glEnable(GL_COLOR_MATERIAL);");
glEnable(GL_COLOR_MATERIAL);
WriteLog("glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);");
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColor4fv(Global::whiteLight);
// WriteLog("glMaterialfv( GL_FRONT, GL_AMBIENT, whiteLight );");
// glMaterialfv( GL_FRONT, GL_AMBIENT, Global::whiteLight );
WriteLog("glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, whiteLight );");
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Global::whiteLight);
/*
WriteLog("glMaterialfv( GL_FRONT, GL_SPECULAR, noLight );");
glMaterialfv( GL_FRONT, GL_SPECULAR, Global::noLight );
*/
WriteLog("glEnable(GL_LIGHTING);");
glEnable(GL_LIGHTING);
WriteLog("glFogi(GL_FOG_MODE, GL_LINEAR);");
glFogi(GL_FOG_MODE, GL_LINEAR); // Fog Mode
WriteLog("glFogfv(GL_FOG_COLOR, FogColor);");
GLfloat FogColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glFogfv(GL_FOG_COLOR, FogColor); // Set Fog Color
// glFogf(GL_FOG_DENSITY, 0.594f); // How Dense Will The
//Fog
// Be
// glHint(GL_FOG_HINT, GL_NICEST); // Fog Hint Value
WriteLog("glFogf(GL_FOG_START, 1000.0f);");
glFogf(GL_FOG_START, 10.0f); // Fog Start Depth
WriteLog("glFogf(GL_FOG_END, 2000.0f);");
glFogf(GL_FOG_END, 200.0f); // Fog End Depth
WriteLog("glEnable(GL_FOG);");
glEnable(GL_FOG); // Enables GL_FOG
// Ra: ustawienia testowe
@@ -472,39 +395,49 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
SetForegroundWindow(hWnd);
WriteLog("Sound Init");
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDisable( GL_DEPTH_TEST ); // Disables depth testing
#ifndef EU07_USE_OLD_LIGHTING_MODEL
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
#endif
glLoadIdentity();
// glColor4f(0.3f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0.0f, 0.0f, -0.50f);
// glTranslatef(0.0f, 0.0f, -0.50f);
// glRasterPos2f(-0.25f, -0.10f);
glDisable(GL_DEPTH_TEST); // Disables depth testing
glColor3f(3.0f, 3.0f, 3.0f);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
glColor3f( 3.0f, 3.0f, 3.0f );
#else
glColor3f( 1.0f, 1.0f, 1.0f );
#endif
auto logo = TextureManager.GetTextureId( "logo", szTexturePath, 6 );
TextureManager.Bind(logo); // Select our texture
auto logo = GfxRenderer.GetTextureId( "logo", szTexturePath, 6 );
GfxRenderer.Bind(logo); // Select our texture
float const widthratio = ( 4.0f / 3.0f ) / ( (float)Global::iWindowWidth / Global::iWindowHeight );
glBegin(GL_QUADS); // Drawing using triangles
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-0.28f, -0.22f, 0.0f); // bottom left of the texture and quad
glVertex2f( -widthratio, -1.0f ); // bottom left of the texture and quad
glTexCoord2f(1.0f, 0.0f);
glVertex3f(0.28f, -0.22f, 0.0f); // bottom right of the texture and quad
glVertex2f(widthratio, -1.0f); // bottom right of the texture and quad
glTexCoord2f(1.0f, 1.0f);
glVertex3f(0.28f, 0.22f, 0.0f); // top right of the texture and quad
glVertex2f(widthratio, 1.0f); // top right of the texture and quad
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-0.28f, 0.22f, 0.0f); // top left of the texture and quad
glVertex2f( -widthratio, 1.0f ); // top left of the texture and quad
glEnd();
//~logo; Ra: to jest bez sensu zapis
glColor3f(0.0f, 0.0f, 100.0f);
glColor3f(0.0f, 0.0f, 1.0f);
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.09f);
glRasterPos2f(-0.85f * widthratio, -0.25f);
glPrint("Uruchamianie / Initializing...");
glRasterPos2f(-0.25f, -0.10f);
glRasterPos2f(-0.85f * widthratio, -0.30f);
glPrint("Dzwiek / Sound...");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
glEnable(GL_LIGHTING);
/*-----------------------Sound Initialization-----------------------*/
TSoundsManager::Init(hWnd);
// TSoundsManager::LoadSounds( "" );
@@ -512,7 +445,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Sound Init OK");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.11f);
glRasterPos2f(-0.25f * widthratio, -0.30f);
glPrint("OK.");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -523,7 +456,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Textures init");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.12f);
glRasterPos2f(-0.85f * widthratio, -0.35f);
glPrint("Tekstury / Textures...");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -533,7 +466,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Textures init OK");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.13f);
glRasterPos2f( -0.25f * widthratio, -0.35f );
glPrint("OK.");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -541,7 +474,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Models init");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.14f);
glRasterPos2f( -0.85f * widthratio, -0.40f );
glPrint("Modele / Models...");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -551,7 +484,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Models init OK");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.15f);
glRasterPos2f( -0.25f * widthratio, -0.40f );
glPrint("OK.");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -559,18 +492,35 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Ground init");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.16f);
glRasterPos2f( -0.85f * widthratio, -0.45f );
glPrint("Sceneria / Scenery (please wait)...");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
#ifndef EU07_USE_OLD_LIGHTING_MODEL
// setup lighting
// GLfloat ambient[] = { 0.65f, 0.65f, 0.65f, 0.5f };
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
Global::DayLight.id = opengl_renderer::sunlight;
// directional light
// TODO, TBD: test omni-directional variant
Global::DayLight.position[ 3 ] = 1.0f;
::glLightf( opengl_renderer::sunlight, GL_SPOT_CUTOFF, 90.0 );
// rgb value for 5780 kelvin
Global::DayLight.diffuse[ 0 ] = 255.0 / 255.0;
Global::DayLight.diffuse[ 1 ] = 242.0 / 255.0;
Global::DayLight.diffuse[ 2 ] = 231.0 / 255.0;
#endif
Ground.Init(Global::SceneryFile, hDC);
// Global::tSinceStart= 0;
Clouds.Init();
Environment.init();
WriteLog("Ground init OK");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.17f);
glRasterPos2f( -0.25f * widthratio, -0.45f );
glPrint("OK.");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -587,7 +537,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
char buff[255] = "Player train init: ";
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.18f);
glRasterPos2f( -0.85f * widthratio, -0.50f );
glPrint("Przygotowanie kabiny do sterowania...");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -608,7 +558,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
WriteLog("Player train init OK");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.19f);
glRasterPos2f( -0.25f * widthratio, -0.50f );
glPrint("OK.");
}
FollowView();
@@ -620,7 +570,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
FreeFlyModeFlag = true; // Ra: automatycznie włączone latanie
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.20f);
glRasterPos2f( -0.85f * widthratio, -0.50f );
glPrint("Blad inicjalizacji sterowanego pojazdu!");
}
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
@@ -636,7 +586,7 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
Error("Player train not exist!");
if (Global::detonatoryOK)
{
glRasterPos2f(-0.25f, -0.20f);
glRasterPos2f( -0.85f * widthratio, -0.55f );
glPrint("Wybrany pojazd nie istnieje w scenerii!");
}
}
@@ -664,9 +614,9 @@ bool TWorld::Init(HWND NhWnd, HDC hDC)
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); //{Texture blends with object
// background}
if (Global::bOldSmudge == true)
light = TextureManager.GetTextureId( "smuga.tga", szTexturePath );
light = GfxRenderer.GetTextureId( "smuga.tga", szTexturePath );
else
light = TextureManager.GetTextureId( "smuga2.tga", szTexturePath );
light = GfxRenderer.GetTextureId( "smuga2.tga", szTexturePath );
// Camera.Reset();
Timer::ResetTimers();
WriteLog( "Load time: " +
@@ -766,59 +716,102 @@ void TWorld::OnKeyDown(int cKey)
}
else if ((cKey >= VK_F1) ? (cKey <= VK_F12) : false)
{
switch (cKey)
{
case VK_F1: // czas i relacja
case VK_F3:
case VK_F5: // przesiadka do innego pojazdu
case VK_F8: // FPS
case VK_F9: // wersja, typ wyświetlania, błędy OpenGL
case VK_F10:
if (Global::iTextMode == cKey)
Global::iTextMode =
(Global::iPause && (cKey != VK_F1) ? VK_F1 :
0); // wyłączenie napisów, chyba że pauza
else
Global::iTextMode = cKey;
break;
case VK_F2: // parametry pojazdu
if (Global::iTextMode == cKey) // jeśli kolejne naciśnięcie
++Global::iScreenMode[cKey - VK_F1]; // kolejny ekran
else
{ // pierwsze naciśnięcie daje pierwszy (tzn. zerowy) ekran
Global::iTextMode = cKey;
Global::iScreenMode[cKey - VK_F1] = 0;
switch (cKey) {
case VK_F1: {
if( DebugModeFlag ) {
// additional time speedup keys in debug mode
if( Console::Pressed( VK_CONTROL ) ) {
// ctrl-f3
GlobalTime->UpdateMTableTime( 20.0 * 60.0 );
}
else if( Console::Pressed( VK_SHIFT ) ) {
// shift-f3
GlobalTime->UpdateMTableTime( 5.0 * 60.0 );
}
}
if( ( false == Console::Pressed( VK_CONTROL ) )
&& ( false == Console::Pressed( VK_SHIFT ) ) ) {
// czas i relacja
if( Global::iTextMode == cKey ) {
// wyłączenie napisów, chyba że pauza
Global::iTextMode =
( Global::iPause && ( cKey != VK_F1 ) ?
VK_F1 :
0 );
}
else
Global::iTextMode = cKey;
}
break;
}
break;
case VK_F12: // coś tam jeszcze
if (Console::Pressed(VK_CONTROL) && Console::Pressed(VK_SHIFT))
DebugModeFlag = !DebugModeFlag; // taka opcjonalna funkcja, może się czasem przydać
/* //Ra 2F1P: teraz włączanie i wyłączanie klawiszami cyfrowymi po użyciu [F12]
else if (Console::Pressed(VK_SHIFT))
{//odpalenie logu w razie "W"
if ((Global::iWriteLogEnabled&2)==0) //nie było okienka
{//otwarcie okna
AllocConsole();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);
}
Global::iWriteLogEnabled|=3;
} */
else
case VK_F2: {
// parametry pojazdu
if( Global::iTextMode == cKey ) {
// jeśli kolejne naciśnięcie
++Global::iScreenMode[ cKey - VK_F1 ]; // kolejny ekran
}
else {
// pierwsze naciśnięcie daje pierwszy (tzn. zerowy) ekran
Global::iTextMode = cKey;
Global::iScreenMode[ cKey - VK_F1 ] = 0;
}
break;
}
case VK_F3: {
Global::iTextMode = cKey;
break;
case VK_F4:
InOutKey();
break;
case VK_F6:
if (DebugModeFlag)
{ // przyspieszenie symulacji do testowania scenerii... uwaga na FPS!
// Global::iViewMode=VK_F6;
if (Console::Pressed(VK_CONTROL))
Global::fTimeSpeed = (Console::Pressed(VK_SHIFT) ? 10.0 : 5.0);
break;
}
case VK_F4: {
InOutKey();
break;
}
case VK_F5: {
// przesiadka do innego pojazdu
Global::iTextMode = cKey;
break;
}
case VK_F6: {
Global::iTextMode = cKey;
// przyspieszenie symulacji do testowania scenerii... uwaga na FPS!
if( DebugModeFlag ) {
if( Console::Pressed( VK_CONTROL ) ) { Global::fTimeSpeed = ( Console::Pressed( VK_SHIFT ) ? 60.0 : 20.0 ); }
else { Global::fTimeSpeed = ( Console::Pressed( VK_SHIFT ) ? 5.0 : 1.0 ); }
}
break;
}
case VK_F8: {
Global::iTextMode = cKey;
// FPS
break;
}
case VK_F9: {
Global::iTextMode = cKey;
// wersja, typ wyświetlania, błędy OpenGL
break;
}
case VK_F10: {
if( Global::iTextMode == cKey ) {
Global::iTextMode =
( Global::iPause && ( cKey != VK_F1 ) ?
VK_F1 :
0 ); // wyłączenie napisów, chyba że pauza
}
else {
Global::iTextMode = cKey;
}
break;
}
case VK_F12: {
// coś tam jeszcze
if( Console::Pressed( VK_CONTROL )
&& Console::Pressed( VK_SHIFT ) )
DebugModeFlag = !DebugModeFlag; // taka opcjonalna funkcja, może się czasem przydać
else
Global::fTimeSpeed = (Console::Pressed(VK_SHIFT) ? 2.0 : 1.0);
Global::iTextMode = cKey;
break;
}
break;
}
// if (cKey!=VK_F4)
return; // nie są przekazywane do pojazdu wcale
@@ -984,7 +977,7 @@ void TWorld::OnKeyUp(int cKey)
void TWorld::OnMouseMove(double x, double y)
{ // McZapkie:060503-definicja obracania myszy
Camera.OnCursorMove(x * Global::fMouseXScale, -y * Global::fMouseYScale);
Camera.OnCursorMove(x * Global::fMouseXScale / Global::ZoomFactor, -y * Global::fMouseYScale / Global::ZoomFactor);
}
void TWorld::InOutKey()
@@ -1157,7 +1150,8 @@ bool TWorld::Update()
iCheckFPS = 0.25 * Timer::GetFPS(); // tak za 0.25 sekundy sprawdzić ponownie (jeszcze przycina?)
}
Timer::UpdateTimers(Global::iPause);
if (!Global::iPause)
if( (Global::iPause == false)
|| (m_init == false) )
{ // jak pauza, to nie ma po co tego przeliczać
GlobalTime->UpdateMTableTime(Timer::GetDeltaTime()); // McZapkie-300302: czas rozkladowy
// Ra 2014-07: przeliczenie kąta czasu (do animacji zależnych od czasu)
@@ -1170,7 +1164,7 @@ bool TWorld::Update()
Global::fClockAngleDeg[4] = 36.0 * (GlobalTime->hh % 10); // jednostki godzin
Global::fClockAngleDeg[5] = 36.0 * (GlobalTime->hh / 10); // dziesiątki godzin
Update_Lights();
Update_Environment();
} // koniec działań niewykonywanych podczas pauzy
// poprzednie jakoś tam działało
double dt = Timer::GetDeltaRenderTime(); // nie uwzględnia pauzowania ani mnożenia czasu
@@ -1243,6 +1237,8 @@ bool TWorld::Update()
Ground.CheckQuery();
Ground.Update_Lights();
if( Train != nullptr ) {
TSubModel::iInstance = reinterpret_cast<int>( Train->Dynamic() );
Train->Update( dt );
@@ -1254,13 +1250,17 @@ bool TWorld::Update()
// przy 0.25 smuga gaśnie o 6:37 w Quarku, a mogłaby już 5:40
// Ra 2014-12: przy 0.15 się skarżyli, że nie widać smug => zmieniłem na 0.25
// changed light activation threshold to 0.5, paired with strength reduction in daylight
if (Train) // jeśli nie usunięty
if( Train ) {
// jeśli nie usunięty
Global::bSmudge =
( FreeFlyModeFlag ?
false :
( Train->Dynamic()->fShade <= 0.0 ?
(Global::fLuminance <= 0.5) :
(Train->Dynamic()->fShade * Global::fLuminance <= 0.5) ) );
( Global::fLuminance <= 0.5 ) :
( Train->Dynamic()->fShade * Global::fLuminance <= 0.5 ) ) );
}
m_init = true;
if (!Render())
return false;
@@ -1299,8 +1299,19 @@ TWorld::Update_Camera( double const Deltatime ) {
if( FreeFlyModeFlag )
Camera.RaLook(); // jednorazowe przestawienie kamery
}
else if( Console::Pressed( VK_RBUTTON ) ) //||Console::Pressed(VK_F4))
else if( Console::Pressed( VK_RBUTTON ) ) { //||Console::Pressed(VK_F4))
FollowView( false ); // bez wyciszania dźwięków
}
else if( true == Console::Pressed( VK_MBUTTON ) ) {
// middle mouse button controls zoom.
Global::ZoomFactor = std::min( 4.5f, Global::ZoomFactor + 15.0f * static_cast<float>(Deltatime) );
}
else if( false == Console::Pressed( VK_MBUTTON ) ) {
// reset zoom level if the button is no longer held down.
// NOTE: yes, this is terrible way to go about it. it'll do for now.
Global::ZoomFactor = std::max( 1.0f, Global::ZoomFactor - 15.0f * static_cast<float>( Deltatime ) );
}
/*
else if( Global::iTextMode == -1 ) { // tu mozna dodac dopisywanie do logu przebiegu lokomotywy
WriteLog( "Number of textures used: " + std::to_string( Global::iTextures ) );
@@ -1397,7 +1408,9 @@ TWorld::Update_Camera( double const Deltatime ) {
}
}
void TWorld::Update_Lights() {
void TWorld::Update_Environment() {
#ifdef EU07_USE_OLD_LIGHTING_MODEL
if( Global::fMoveLight < 0.0 ) {
return;
@@ -1480,7 +1493,7 @@ void TWorld::Update_Lights() {
+0.150 * ( Global::diffuseDayLight[ 0 ] + Global::ambientDayLight[ 0 ] ) // R
+ 0.295 * ( Global::diffuseDayLight[ 1 ] + Global::ambientDayLight[ 1 ] ) // G
+ 0.055 * ( Global::diffuseDayLight[ 2 ] + Global::ambientDayLight[ 2 ] ); // B
vector3 sky = vector3( Global::AtmoColor[ 0 ], Global::AtmoColor[ 1 ], Global::AtmoColor[ 2 ] );
if( Global::fLuminance < 0.25 ) { // przyspieszenie zachodu/wschodu
sky *= 4.0 * Global::fLuminance; // nocny kolor nieba
@@ -1493,7 +1506,9 @@ void TWorld::Update_Lights() {
else {
glFogfv( GL_FOG_COLOR, Global::FogColor ); // kolor mgły
}
glClearColor( sky.x, sky.y, sky.z, 0.0 ); // kolor nieba
#else
Environment.update();
#endif
}
bool TWorld::Render()
@@ -1502,42 +1517,26 @@ bool TWorld::Render()
// glColor3b(255, 0, 255);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthFunc( GL_LEQUAL );
glMatrixMode( GL_PROJECTION ); // select the Projection Matrix
glLoadIdentity(); // reset the Projection Matrix
// calculate the aspect ratio of the window
gluPerspective( Global::FieldOfView / Global::ZoomFactor, (GLdouble)Global::ScreenWidth / (GLdouble)Global::ScreenHeight, 0.1f * Global::ZoomFactor, 2500.0f * Global::ZoomFactor );
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity();
Camera.SetMatrix(); // ustawienie macierzy kamery względem początku scenerii
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos);
if (!Global::bWireFrame)
{ // bez nieba w trybie rysowania linii
glDisable(GL_FOG);
Clouds.Render();
glEnable(GL_FOG);
if( !Global::bWireFrame ) {
// bez nieba w trybie rysowania linii
Environment.render();
}
if (Global::bUseVBO)
{ // renderowanie przez VBO
if (!Ground.RenderVBO(Camera.Pos))
return false;
if (!Ground.RenderAlphaVBO(Camera.Pos))
return false;
}
else
{ // renderowanie przez Display List
if (!Ground.RenderDL(Camera.Pos))
return false;
if (!Ground.RenderAlphaDL(Camera.Pos))
return false;
}
/*
TSubModel::iInstance = (int)(Train ? Train->Dynamic() : 0); //żeby nie robić cudzych animacji
// if (Camera.Type==tp_Follow)
if (Train)
Train->Update();
*/
if( false == Ground.Render( Camera.Pos ) ) { return false; }
Render_Cab();
Render_UI();
// glFlush();
// Global::bReCompile=false; //Ra: już zrobiona rekompilacja
ResourceManager::Sweep( Timer::GetSimulationTime() );
return true;
@@ -1562,6 +1561,7 @@ TWorld::Render_Cab() {
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
return;
}
/*
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
if( ( Train->Dynamic()->mdKabina != Train->Dynamic()->mdModel ) &&
@@ -1575,10 +1575,11 @@ TWorld::Render_Cab() {
glLoadIdentity(); // zacząć od macierzy jedynkowej
Camera.SetCabMatrix( pos ); // widok z kamery po przesunięciu
glMultMatrixd( dynamic->mMatrix.getArray() ); // ta macierz nie ma przesunięcia
/*
//*yB: moje smuuugi 1
if( Global::bSmudge ) { // Ra: uwzględniłem zacienienie pojazdu przy zapalaniu smug
// 1. warunek na smugę wyznaczyc wcześniej
// 1. warunek na smugę wyznaczyc wcześniej
// 2. jeśli smuga włączona, nie renderować pojazdu użytkownika w DynObj
// 3. jeśli smuga właczona, wyrenderować pojazd użytkownia po dodaniu smugi do sceny
auto const &frontlights = Train->Controlled()->iLights[ 0 ];
@@ -1605,7 +1606,7 @@ TWorld::Render_Cab() {
glDisable( GL_DEPTH_TEST );
glDisable( GL_LIGHTING );
glDisable( GL_FOG );
TextureManager.Bind( light ); // Select our texture
GfxRenderer.Bind( light ); // Select our texture
glBegin( GL_QUADS );
float fSmudge =
dynamic->MoverParameters->DimHalf.y + 7; // gdzie zaczynać smugę
@@ -1647,28 +1648,29 @@ TWorld::Render_Cab() {
glDisable( GL_LIGHTING );
glDisable( GL_FOG );
//glColor4f(0.15f, 0.15f, 0.15f, 0.25f);
TextureManager.Bind( light ); // Select our texture
GfxRenderer.Bind( light ); // Select our texture
//float ddl = (0.15*Global::diffuseDayLight[0]+0.295*Global::diffuseDayLight[1]+0.055*Global::diffuseDayLight[2]); //0.24:0
glBegin( GL_QUADS );
float fSmudge = dynamic->MoverParameters->DimHalf.y + 7; // gdzie zaczynać smugę
if( frontlightstrength > 0.f ) { // wystarczy jeden zapalony z przodu
if( frontlightstrength > 0.f ) {
// wystarczy jeden zapalony z przodu
for( int i = 15; i <= 35; i++ ) {
float z = i * i * i * 0.01f;//25/4;
//float C = (36 - i*0.5)*0.005*(1.5 - sqrt(ddl));
float C = ( 36 - i*0.5 )*0.005*sqrt( ( 1 / sqrt( Global::fLuminance + 0.015 ) ) - 1 ) * frontlightstrength;
glColor4f( C, C, C, 0.35f );// *frontlightstrength );
glTexCoord2f( 0, 0 ); glVertex3f( -10 / 2 - 2 * i / 4, 6.0 + 0.3*z, 13 + 1.7*z / 3 );
glTexCoord2f( 1, 0 ); glVertex3f( 10 / 2 + 2 * i / 4, 6.0 + 0.3*z, 13 + 1.7*z / 3 );
glTexCoord2f( 1, 1 ); glVertex3f( 10 / 2 + 2 * i / 4, -5.0 - 0.5*z, 13 + 1.7*z / 3 );
glColor4f( C, C, C, 1.0f );// *frontlightstrength );
glTexCoord2f( 0, 0 ); glVertex3f( -10 / 2 - 2 * i / 4, 6.0 + 0.3*z, 13 + 1.7*z / 3 );
glTexCoord2f( 1, 0 ); glVertex3f( 10 / 2 + 2 * i / 4, 6.0 + 0.3*z, 13 + 1.7*z / 3 );
glTexCoord2f( 1, 1 ); glVertex3f( 10 / 2 + 2 * i / 4, -5.0 - 0.5*z, 13 + 1.7*z / 3 );
glTexCoord2f( 0, 1 ); glVertex3f( -10 / 2 - 2 * i / 4, -5.0 - 0.5*z, 13 + 1.7*z / 3 );
}
}
if( rearlightstrength > 0.f ) { // wystarczy jeden zapalony z tyłu
if( rearlightstrength > 0.f ) {
// wystarczy jeden zapalony z tyłu
for( int i = 15; i <= 35; i++ ) {
float z = i * i * i * 0.01f;//25/4;
float C = ( 36 - i*0.5 )*0.005*sqrt( ( 1 / sqrt( Global::fLuminance + 0.015 ) ) - 1 ) * rearlightstrength;
glColor4f( C, C, C, 0.35f );// *rearlightstrength );
glColor4f( C, C, C, 1.0f );// *rearlightstrength );
glTexCoord2f( 0, 0 ); glVertex3f( 10 / 2 + 2 * i / 4, 6.0 + 0.3*z, -13 - 1.7*z / 3 );
glTexCoord2f( 1, 0 ); glVertex3f( -10 / 2 - 2 * i / 4, 6.0 + 0.3*z, -13 - 1.7*z / 3 );
glTexCoord2f( 1, 1 ); glVertex3f( -10 / 2 - 2 * i / 4, -5.0 - 0.5*z, -13 - 1.7*z / 3 );
@@ -1685,17 +1687,23 @@ TWorld::Render_Cab() {
glEnable( GL_FOG );
}
}
glEnable( GL_LIGHTING ); // po renderowaniu smugi jest to wyłączone
// Ra: pojazd użytkownika należało by renderować po smudze, aby go nie rozświetlała
Global::bSmudge = false; // aby model użytkownika się teraz wyrenderował
dynamic->Render();
dynamic->RenderAlpha(); // przezroczyste fragmenty pojazdów na torach
} // yB: moje smuuugi 1 - koniec*/
} // yB: moje smuuugi 1 - koniec
else
glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone
*/ glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit
if( dynamic->mdKabina ) // bo mogła zniknąć przy przechodzeniu do innego pojazdu
{ // oswietlenie kabiny
{
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
// oswietlenie kabiny
GLfloat ambientCabLight[ 4 ] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat diffuseCabLight[ 4 ] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat specularCabLight[ 4 ] = { 0.5f, 0.5f, 0.5f, 1.0f };
@@ -1775,6 +1783,14 @@ TWorld::Render_Cab() {
glLightfv( GL_LIGHT0, GL_AMBIENT, ambientCabLight );
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuseCabLight );
glLightfv( GL_LIGHT0, GL_SPECULAR, specularCabLight );
#else
if( dynamic->InteriorLightLevel > 0.0f ) {
// crude way to light the cabin, until we have something more complete in place
auto const cablight = dynamic->InteriorLight * dynamic->InteriorLightLevel;
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x );
}
#endif
if( Global::bUseVBO ) { // renderowanie z użyciem VBO
dynamic->mdKabina->RaRender( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
dynamic->mdKabina->RaRenderAlpha( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
@@ -1783,10 +1799,19 @@ TWorld::Render_Cab() {
dynamic->mdKabina->Render( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
dynamic->mdKabina->RenderAlpha( 0.0, dynamic->ReplacableSkinID, dynamic->iAlpha );
}
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
// przywrócenie standardowych, bo zawsze są zmieniane
glLightfv( GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight );
glLightfv( GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight );
glLightfv( GL_LIGHT0, GL_SPECULAR, Global::specularDayLight );
#else
if( dynamic->InteriorLightLevel > 0.0f ) {
// reset the overall ambient
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
}
#endif
}
glPopMatrix();
}
@@ -1794,10 +1819,18 @@ TWorld::Render_Cab() {
void
TWorld::Render_UI() {
// set the UI mode projection. TODO: rework it all into somethinig more elegant... eventually
glMatrixMode( GL_PROJECTION ); // select the Projection Matrix
glLoadIdentity(); // reset the Projection Matrix
// calculate the aspect ratio of the window
gluPerspective( 45.0f, (GLdouble)Global::ScreenWidth / (GLdouble)Global::ScreenHeight, 0.2f, 2500.0f );
glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
glLoadIdentity();
if( DebugModeFlag && !Global::iTextMode ) {
OutText1 = " FPS: ";
OutText1 = "FPS: ";
OutText1 += to_string( Timer::GetFPS(), 2 );
OutText1 += Global::iSlowMotion ? "s" : "n";
OutText1 += Global::iSlowMotion ? "(s)" : "(n)";
OutText1 += ( Timer::GetDeltaTime() >= 0.2 ) ? "!" : " ";
// if (GetDeltaTime()>=0.2) //Ra: to za bardzo miota tekstem!
@@ -1812,7 +1845,7 @@ TWorld::Render_UI() {
if( Global::iTextMode == VK_F8 ) {
Global::iViewMode = VK_F8;
OutText1 = " FPS: ";
OutText1 = "FPS: ";
OutText1 += to_string( Timer::GetFPS(), 2 );
//OutText1 += sprintf();
if( Global::iSlowMotion )
@@ -1948,7 +1981,7 @@ TWorld::Render_UI() {
SetWindowText( hWnd, Controlled->MoverParameters->Name.c_str() );
else
SetWindowText( hWnd, Global::SceneryFile.c_str() ); // nazwa scenerii
TextureManager.Bind( 0 );
GfxRenderer.Bind( 0 );
glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
glLoadIdentity();
glTranslatef( 0.0f, 0.0f, -0.50f );
@@ -2247,7 +2280,9 @@ TWorld::Render_UI() {
OutText1 +=
" " +
std::string( "S SEE NEN NWW SW" )
.substr( 1 + 2 * floor( fmod( 8 + ( Camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
.substr( 0 + 2 * floor( fmod( 8 + ( Camera.Yaw + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 );
// current luminance level
OutText2 = "Light level: " + to_string( Global::fLuminance, 3 );
}
// OutText3= AnsiString(" Online documentation (PL, ENG, DE, soon CZ):
// http://www.eu07.pl");
@@ -2943,3 +2978,79 @@ void TWorld::CabChange(TDynamicObject *old, TDynamicObject *now)
Global::changeDynObj = now; // uruchomienie protezy
};
//---------------------------------------------------------------------------
void
world_environment::init() {
m_sun.init();
m_stars.init();
m_clouds.Init();
}
void
world_environment::update() {
// move sun...
m_sun.update();
auto const position = m_sun.getPosition();
// ...update the global data to match new sun state...
Global::SunAngle = m_sun.getAngle();
Global::DayLight.set_position( position );
Global::DayLight.direction = -1.0 * m_sun.getDirection();
// ...update skydome to match the current sun position as well...
m_skydome.Update( position );
// ...retrieve current sky colour and brightness...
auto const skydomecolour = m_skydome.GetAverageColor();
auto const skydomehsv = RGBtoHSV( skydomecolour );
auto const intensity = std::min( 1.15f * (0.05f + m_sun.getIntensity() + skydomehsv.z), 1.25f );
// ...update light colours and intensity.
// NOTE: intensity combines intensity of the sun and the light reflected by the sky dome
// it'd be more technically correct to have just the intensity of the sun here,
// but whether it'd _look_ better is something to be tested
Global::DayLight.diffuse[ 0 ] = intensity * 255.0f / 255.0f;
Global::DayLight.diffuse[ 1 ] = intensity * 242.0f / 255.0f;
Global::DayLight.diffuse[ 2 ] = intensity * 231.0f / 255.0f;
Global::DayLight.ambient[ 0 ] = skydomecolour.x;
Global::DayLight.ambient[ 1 ] = skydomecolour.y;
Global::DayLight.ambient[ 2 ] = skydomecolour.z;
Global::fLuminance = intensity;
// update the fog. setting it to match the average colour of the sky dome is cheap
// but quite effective way to make the distant items blend with background better
Global::FogColor[ 0 ] = skydomecolour.x;
Global::FogColor[ 1 ] = skydomecolour.y;
Global::FogColor[ 2 ] = skydomecolour.z;
::glFogfv( GL_FOG_COLOR, Global::FogColor ); // kolor mgły
::glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f ); // kolor nieba
}
void
world_environment::render() {
::glDisable( GL_LIGHTING );
::glDisable( GL_FOG );
::glDisable( GL_DEPTH_TEST );
::glDepthMask( GL_FALSE );
::glPushMatrix();
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
m_skydome.Render();
m_stars.render();
m_clouds.Render( m_skydome.GetAverageColor() * 2.5f );
if( DebugModeFlag == true ) {
// mark sun position for easier debugging
m_sun.render();
}
Global::DayLight.apply_angle();
Global::DayLight.apply_intensity();
::glPopMatrix();
::glDepthMask( GL_TRUE );
::glEnable( GL_DEPTH_TEST );
::glEnable( GL_FOG );
::glEnable( GL_LIGHTING );
}

24
World.h
View File

@@ -13,8 +13,26 @@ http://mozilla.org/MPL/2.0/.
#include "Camera.h"
#include "Ground.h"
#include "sky.h"
#include "sun.h"
#include "stars.h"
#include "skydome.h"
#include "mczapkie/mover.h"
// wrapper for environment elements -- sky, sun, stars, clouds etc
class world_environment {
public:
void init();
void update();
void render();
private:
CSkyDome m_skydome;
cStars m_stars;
cSun m_sun;
TSky m_clouds;
};
class TWorld
{
void InOutKey();
@@ -40,19 +58,19 @@ class TWorld
std::string OutText2;
std::string OutText3;
std::string OutText4;
void Update_Lights();
void Update_Environment();
void Update_Camera( const double Deltatime );
bool Render();
void Render_Cab();
void Render_UI();
TCamera Camera;
TGround Ground;
world_environment Environment;
TTrain *Train;
TDynamicObject *pDynamicNearest;
bool Paused;
GLuint base; // numer DL dla znaków w napisach
texture_manager::size_type light; // numer tekstury dla smugi
TSky Clouds;
TEvent *KeyEvents[10]; // eventy wyzwalane z klawiaury
TMoverParameters *mvControlled; // wskaźnik na człon silnikowy, do wyświetlania jego parametrów
int iCheckFPS; // kiedy znów sprawdzić FPS, żeby wyłączać optymalizacji od razu do zera
@@ -63,10 +81,12 @@ class TWorld
double VelPrev; // poprzednia prędkość
int tprev; // poprzedni czas
double Acc; // przyspieszenie styczne
bool m_init{ false }; // indicates whether initial update of the world was performed
public:
void ModifyTGA(std::string const &dir = "");
void CreateE3D(std::string const &dir = "", bool dyn = false);
void CabChange(TDynamicObject *old, TDynamicObject *now);
};
//---------------------------------------------------------------------------

118
color.h Normal file
View File

@@ -0,0 +1,118 @@
#pragma once
#include "float3d.h"
inline
float3
XYZtoRGB( float3 const &XYZ ) {
// M^-1 for Adobe RGB from http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html
float const mi[ 3 ][ 3 ] = { 2.041369, -0.969266, 0.0134474, -0.5649464, 1.8760108, -0.1183897, -0.3446944, 0.041556, 1.0154096 };
// m^-1 for sRGB:
// float const mi[ 3 ][ 3 ] = { 3.240479, -0.969256, 0.055648, -1.53715, 1.875991, -0.204043, -0.49853, 0.041556, 1.057311 };
return float3{
XYZ.x*mi[ 0 ][ 0 ] + XYZ.y*mi[ 1 ][ 0 ] + XYZ.z*mi[ 2 ][ 0 ],
XYZ.x*mi[ 0 ][ 1 ] + XYZ.y*mi[ 1 ][ 1 ] + XYZ.z*mi[ 2 ][ 1 ],
XYZ.x*mi[ 0 ][ 2 ] + XYZ.y*mi[ 1 ][ 2 ] + XYZ.z*mi[ 2 ][ 2 ] };
}
inline
float3
RGBtoHSV( float3 const &RGB ) {
float3 hsv;
float const max = std::max( std::max( RGB.x, RGB.y ), RGB.z );
float const min = std::min( std::min( RGB.x, RGB.y ), RGB.z );
float const delta = max - min;
hsv.z = max; // v
if( delta < 0.00001 ) {
hsv.y = 0;
hsv.x = 0; // undefined, maybe nan?
return hsv;
}
if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
hsv.y = ( delta / max ); // s
}
else {
// if max is 0, then r = g = b = 0
// s = 0, v is undefined
hsv.y = 0.0;
hsv.x = NAN; // its now undefined
return hsv;
}
if( RGB.x >= max ) // > is bogus, just keeps compilor happy
hsv.x = ( RGB.y - RGB.z ) / delta; // between yellow & magenta
else
if( RGB.y >= max )
hsv.x = 2.0 + ( RGB.y - RGB.x ) / delta; // between cyan & yellow
else
hsv.x = 4.0 + ( RGB.x - RGB.y ) / delta; // between magenta & cyan
hsv.x *= 60.0; // degrees
if( hsv.x < 0.0 )
hsv.x += 360.0;
return hsv;
}
inline
float3
HSVtoRGB( float3 const &HSV ) {
float3 rgb;
if( HSV.y <= 0.0 ) { // < is bogus, just shuts up warnings
rgb.x = HSV.z;
rgb.y = HSV.z;
rgb.z = HSV.z;
return rgb;
}
float hh = HSV.x;
if( hh >= 360.0 ) hh = 0.0;
hh /= 60.0;
int const i = (int)hh;
float const ff = hh - i;
float const p = HSV.z * ( 1.0 - HSV.y );
float const q = HSV.z * ( 1.0 - ( HSV.y * ff ) );
float const t = HSV.z * ( 1.0 - ( HSV.y * ( 1.0 - ff ) ) );
switch( i ) {
case 0:
rgb.x = HSV.z;
rgb.y = t;
rgb.z = p;
break;
case 1:
rgb.x = q;
rgb.y = HSV.z;
rgb.z = p;
break;
case 2:
rgb.x = p;
rgb.y = HSV.z;
rgb.z = t;
break;
case 3:
rgb.x = p;
rgb.y = q;
rgb.z = HSV.z;
break;
case 4:
rgb.x = t;
rgb.y = p;
rgb.z = HSV.z;
break;
case 5:
default:
rgb.x = HSV.z;
rgb.y = p;
rgb.z = q;
break;
}
return rgb;
}

View File

@@ -83,7 +83,8 @@ class vector3
void inline Normalize();
void inline SafeNormalize();
double inline Length();
double inline Length() const;
double inline LengthSquared() const;
void inline Zero()
{
x = y = z = 0.0;
@@ -415,6 +416,11 @@ inline vector3 CrossProduct(const vector3 &v1, const vector3 &v2)
return vector3(v1.y * v2.z - v1.z * v2.y, v2.x * v1.z - v2.z * v1.x, v1.x * v2.y - v1.y * v2.x);
}
inline vector3 Interpolate( vector3 const &First, vector3 const &Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
inline vector3 operator*(const matrix4x4 &m, const vector3 &v)
{
return vector3(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0],
@@ -430,11 +436,16 @@ void inline vector3::Normalize()
z *= il;
}
double inline vector3::Length()
double inline vector3::Length() const
{
return SQRT_FUNCTION(x * x + y * y + z * z);
}
double inline vector3::LengthSquared() const {
return ( x * x + y * y + z * z );
}
inline bool operator==(const matrix4x4 &m1, const matrix4x4 &m2)
{
for (int x = 0; x < 4; ++x)

86
lightarray.cpp Normal file
View File

@@ -0,0 +1,86 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include "stdafx.h"
#include "lightarray.h"
#include "dynobj.h"
#include "driver.h"
void
light_array::insert( TDynamicObject const *Owner ) {
// we're only storing lights for locos, which have two sets of lights, front and rear
// for a more generic role this function would have to be tweaked to add vehicle type-specific light combinations
data.emplace_back( Owner, 0 );
data.emplace_back( Owner, 1 );
}
void
light_array::remove( TDynamicObject const *Owner ) {
data.erase(
std::remove_if(
data.begin(),
data.end(),
[=]( light_record const &light ){ return light.owner == Owner; } ),
data.end() );
}
// updates records in the collection
void
light_array::update() {
for( auto &light : data ) {
// update light parameters to match current data of the owner
if( light.index == 0 ) {
// front light set
light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.45 );
light.direction = light.owner->VectorFront();
}
else {
// rear light set
light.position = light.owner->GetPosition() - ( light.owner->VectorFront() * light.owner->GetLength() * 0.45 );
light.direction = light.owner->VectorFront();
light.direction.x = -light.direction.x;
light.direction.z = -light.direction.z;
}
// determine intensity of this light set
if( true == light.owner->MoverParameters->Battery ) {
// with battery 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.intensity = 0.15f * light.count; // TODO: intensity can be affected further by dim switch or other factors
// crude catch for unmanned modules which share the light state with the controlled unit.
// why don't they get their own light bits btw ._.
// TODO, TBD: have separate light bits for each vehicle, so this override isn't necessary
if( ( light.owner->Controller == AIdriver )
&& ( light.owner->Mechanik == nullptr ) ) {
light.intensity = 0.0f;
light.count = 0;
}
}
else {
// with battery off the lights are off
light.intensity = 0.0f;
light.count = 0;
}
}
}

45
lightarray.h Normal file
View File

@@ -0,0 +1,45 @@
#pragma once
#include <vector>
#include "dumb3d.h"
#include "float3d.h"
#include "dynobj.h"
// collection of virtual light sources present in the scene
// used by the renderer to determine most suitable placement for actual light sources during render
struct light_array {
public:
// types
struct light_record {
light_record( TDynamicObject const *Owner, int const Lightindex) :
owner(Owner), index(Lightindex)
{};
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
Math3D::vector3 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
float intensity{ 0.0f }; // (combined) intensity of the light(s)
int count{ 0 }; // number (or pattern) of active light(s)
};
// methods
// adds records for lights of specified owner to the collection
void
insert( TDynamicObject const *Owner );
// removes records for lights of specified owner from the collection
void
remove( TDynamicObject const *Owner );
// updates records in the collection
void
update();
// types
typedef std::vector<light_record> lightrecord_array;
// members
lightrecord_array data;
};

View File

@@ -1,5 +1,4 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1

View File

@@ -104,6 +104,7 @@
<ClCompile Include="Gauge.cpp" />
<ClCompile Include="Globals.cpp" />
<ClCompile Include="Ground.cpp" />
<ClCompile Include="lightarray.cpp" />
<ClCompile Include="Logs.cpp" />
<ClCompile Include="mczapkie\friction.cpp" />
<ClCompile Include="mczapkie\hamulce.cpp" />
@@ -119,15 +120,19 @@
<ClCompile Include="parser.cpp" />
<ClCompile Include="PyInt.cpp" />
<ClCompile Include="RealSound.cpp" />
<ClCompile Include="renderer.cpp" />
<ClCompile Include="ResourceManager.cpp" />
<ClCompile Include="Segment.cpp" />
<ClCompile Include="sky.cpp" />
<ClCompile Include="skydome.cpp" />
<ClCompile Include="Sound.cpp" />
<ClCompile Include="Spring.cpp" />
<ClCompile Include="stars.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="sun.cpp" />
<ClCompile Include="Texture.cpp" />
<ClCompile Include="TextureDDS.cpp" />
<ClCompile Include="Timer.cpp" />
@@ -147,6 +152,7 @@
<ClInclude Include="Button.h" />
<ClInclude Include="Camera.h" />
<ClInclude Include="Classes.h" />
<ClInclude Include="color.h" />
<ClInclude Include="Console.h" />
<ClInclude Include="Console\LPT.h" />
<ClInclude Include="Console\MWD.h" />
@@ -161,6 +167,7 @@
<ClInclude Include="Gauge.h" />
<ClInclude Include="Globals.h" />
<ClInclude Include="Ground.h" />
<ClInclude Include="lightarray.h" />
<ClInclude Include="Logs.h" />
<ClInclude Include="McZapkie\friction.h" />
<ClInclude Include="McZapkie\hamulce.h" />
@@ -179,13 +186,17 @@
<ClInclude Include="PyInt.h" />
<ClInclude Include="python\include\Python.h" />
<ClInclude Include="RealSound.h" />
<ClInclude Include="renderer.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="ResourceManager.h" />
<ClInclude Include="Segment.h" />
<ClInclude Include="sky.h" />
<ClInclude Include="skydome.h" />
<ClInclude Include="Sound.h" />
<ClInclude Include="Spring.h" />
<ClInclude Include="stars.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="sun.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="Texture.h" />
<ClInclude Include="TextureDDS.h" />

View File

@@ -189,6 +189,21 @@
<ClCompile Include="Names.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sun.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="renderer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="skydome.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stars.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="lightarray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="opengl\glew.h">
@@ -365,6 +380,24 @@
<ClInclude Include="Console\MWD.h">
<Filter>Header Files\console</Filter>
</ClInclude>
<ClInclude Include="sun.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="renderer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="skydome.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="color.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stars.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="lightarray.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

View File

@@ -67,6 +67,7 @@ cParser::~cParser()
// methods
bool cParser::getTokens(int Count, bool ToLower, const char *Break)
{
tokens.clear(); // emulates old parser behaviour. TODO, TBD: allow manual reset?
/*
if (LoadTraction==true)
trtest="niemaproblema"; //wczytywać

93
renderer.cpp Normal file
View File

@@ -0,0 +1,93 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "renderer.h"
#include "globals.h"
opengl_renderer GfxRenderer;
void
opengl_renderer::Init() {
// create dynamic light pool
for( int idx = 0; idx < Global::DynamicLightCount; ++idx ) {
opengl_light light;
light.id = GL_LIGHT1 + idx;
light.position[ 3 ] = 1.0f;
::glLightf( light.id, GL_SPOT_CUTOFF, 20.0f );
::glLightf( light.id, GL_SPOT_EXPONENT, 10.0f );
::glLightf( light.id, GL_CONSTANT_ATTENUATION, 0.0f );
::glLightf( light.id, GL_LINEAR_ATTENUATION, 0.035f );
m_lights.emplace_back( light );
}
}
void
opengl_renderer::Update_Lights( light_array const &Lights ) {
int const count = std::min( m_lights.size(), Lights.data.size() );
if( count == 0 ) { return; }
auto renderlight = m_lights.begin();
for( auto const &scenelight : Lights.data ) {
if( renderlight == m_lights.end() ) {
// we ran out of lights to assign
break;
}
if( scenelight.intensity == 0.0f ) {
// all lights past this one are bound to be off
break;
}
if( ( Global::pCameraPosition - scenelight.position ).Length() > 1000.0f ) {
// we don't care about lights past arbitrary limit of 1 km.
// but there could still be weaker lights which are closer, so keep looking
continue;
}
// if the light passed tests so far, it's good enough
renderlight->set_position( scenelight.position );
renderlight->direction = scenelight.direction;
renderlight->diffuse[ 0 ] = scenelight.color.x;
renderlight->diffuse[ 1 ] = scenelight.color.y;
renderlight->diffuse[ 2 ] = scenelight.color.z;
renderlight->ambient[ 0 ] = scenelight.color.x * scenelight.intensity;
renderlight->ambient[ 1 ] = scenelight.color.y * scenelight.intensity;
renderlight->ambient[ 2 ] = scenelight.color.z * scenelight.intensity;
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, 0.3f / std::pow( scenelight.count, 2 ) );
::glEnable( renderlight->id );
renderlight->apply_intensity();
renderlight->apply_angle();
++renderlight;
}
while( renderlight != m_lights.end() ) {
// if we went through all scene lights and there's still opengl lights remaining, kill these
::glDisable( renderlight->id );
++renderlight;
}
}
void
opengl_renderer::Disable_Lights() {
for( int idx = 0; idx < m_lights.size() + 1; ++idx ) {
::glDisable( GL_LIGHT0 + idx );
}
}
//---------------------------------------------------------------------------

125
renderer.h Normal file
View File

@@ -0,0 +1,125 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "opengl/glew.h"
#include "texture.h"
#include "lightarray.h"
#include "dumb3d.h"
struct opengl_light {
GLuint id{ -1 };
Math3D::vector3 direction;
GLfloat position[ 4 ]; // 4th parameter specifies directional(0) or omni-directional(1) light source
GLfloat ambient[ 4 ];
GLfloat diffuse[ 4 ];
GLfloat specular[ 4 ];
opengl_light() {
position[ 0 ] = position[ 1 ] = position[ 2 ] = 0.0f; position[ 3 ] = 1.0f; // 0,0,0,1
ambient[ 0 ] = ambient[ 1 ] = ambient[ 2 ] = 0.0f; ambient[ 3 ] = 1.0f; // 0,0,0,1
diffuse[ 0 ] = diffuse[ 1 ] = diffuse[ 2 ] = diffuse[ 3 ] = 1.0f; // 1,1,1,1
specular[ 0 ] = specular[ 1 ] = specular[ 2 ] = specular[ 3 ] = 1.0f; // 1,1,1,1
}
inline
void apply_intensity() {
glLightfv( id, GL_AMBIENT, ambient );
glLightfv( id, GL_DIFFUSE, diffuse );
glLightfv( id, GL_SPECULAR, specular );
}
inline
void apply_angle() {
glLightfv( id, GL_POSITION, position );
if( position[ 3 ] == 1.0f ) {
GLfloat directionarray[] = { direction.x, direction.y, direction.z };
glLightfv( id, GL_SPOT_DIRECTION, directionarray );
}
}
inline
void set_position( Math3D::vector3 const &Position ) {
position[ 0 ] = Position.x;
position[ 1 ] = Position.y;
position[ 2 ] = Position.z;
}
};
// encapsulates basic rendering setup.
// for modern opengl this translates to a specific collection of glsl shaders,
// for legacy opengl this is combination of blending modes, active texture units etc
struct opengl_technique {
};
// a collection of parameters for the rendering setup.
// for modern opengl this translates to set of attributes for the active shaders,
// for legacy opengl this is basically just texture(s) assigned to geometry
struct opengl_material {
};
// bare-bones render controller, in lack of anything better yet
class opengl_renderer {
public:
// types
// methods
void
Init();
void
Update_Lights( light_array const &Lights );
void
Disable_Lights();
texture_manager::size_type
GetTextureId( std::string Filename, std::string const &Dir, int const Filter = -1, bool const Loadnow = true ) {
return m_textures.GetTextureId( Filename, Dir, Filter, Loadnow );
}
void
Bind( texture_manager::size_type const Id ) {
// temporary until we separate the renderer
m_textures.Bind( Id );
}
opengl_texture &
Texture( texture_manager::size_type const Id ) {
return m_textures.Texture( Id );
}
// members
GLenum static const sunlight{ GL_LIGHT0 };
private:
// types
enum class rendermode {
color
};
typedef std::vector<opengl_light> opengllight_array;
// members
rendermode renderpass{ rendermode::color };
opengllight_array m_lights;
texture_manager m_textures;
};
extern opengl_renderer GfxRenderer;
//---------------------------------------------------------------------------

31
sky.cpp
View File

@@ -22,23 +22,23 @@ TSky::TSky(){};
void TSky::Init()
{
WriteLog(Global::asSky.c_str());
WriteLog("init");
WriteLog( "Clouds init" );
if ((Global::asSky != "1") && (Global::asSky != "0"))
// {
mdCloud = TModelsManager::GetModel(Global::asSky.c_str());
// }
mdCloud = TModelsManager::GetModel( Global::asSky );
};
void TSky::Render()
void TSky::Render( float3 const &Tint )
{
if (mdCloud)
{ // jeśli jest model nieba
glPushMatrix();
// glDisable(GL_DEPTH_TEST);
glTranslatef(Global::pCameraPosition.x, Global::pCameraPosition.y,
Global::pCameraPosition.z);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
#else
::glEnable( GL_LIGHTING );
GfxRenderer.Disable_Lights();
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x );
#endif
if (Global::bUseVBO)
{ // renderowanie z VBO
mdCloud->RaRender(100, 0);
@@ -49,11 +49,16 @@ void TSky::Render()
mdCloud->Render(100, 0);
mdCloud->RenderAlpha(100, 0);
}
// glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
// glEnable(GL_LIGHTING);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
glPopMatrix();
// TODO: re-implement this
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos);
#else
GLfloat noambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, noambient );
::glEnable( GL_LIGHT0 ); // other lights will be enabled during lights update
::glDisable( GL_LIGHTING );
#endif
}
};

3
sky.h
View File

@@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/.
#pragma once
#include "Model3d.h"
#include "Float3d.h"
class TSky
{
@@ -21,7 +22,7 @@ class TSky
TSky();
~TSky();
void Init();
void Render();
void Render( float3 const &Tint = float3(1.0f, 1.0f, 1.0f) );
};
//---------------------------------------------------------------------------

344
skydome.cpp Normal file
View File

@@ -0,0 +1,344 @@
#include "stdafx.h"
#include "opengl/glew.h"
#include "skydome.h"
#include "color.h"
// sky gradient based on "A practical analytic model for daylight"
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
float CSkyDome::m_distributionluminance[ 5 ][ 2 ] = { // Perez distributions
{ 0.17872f , -1.46303f }, // a = darkening or brightening of the horizon
{ -0.35540f , 0.42749f }, // b = luminance gradient near the horizon,
{ -0.02266f , 5.32505f }, // c = relative intensity of the circumsolar region
{ 0.12064f , -2.57705f }, // d = width of the circumsolar region
{ -0.06696f , 0.37027f } // e = relative backscattered light
};
float CSkyDome::m_distributionxcomp[ 5 ][ 2 ] = {
{ -0.01925f , -0.25922f },
{ -0.06651f , 0.00081f },
{ -0.00041f , 0.21247f },
{ -0.06409f , -0.89887f },
{ -0.00325f , 0.04517f }
};
float CSkyDome::m_distributionycomp[ 5 ][ 2 ] = {
{ -0.01669f , -0.26078f },
{ -0.09495f , 0.00921f },
{ -0.00792f , 0.21023f },
{ -0.04405f , -1.65369f },
{ -0.01092f , 0.05291f }
};
float CSkyDome::m_zenithxmatrix[ 3 ][ 4 ] = {
{ 0.00165f, -0.00375f, 0.00209f, 0.00000f },
{ -0.02903f, 0.06377f, -0.03202f, 0.00394f },
{ 0.11693f, -0.21196f, 0.06052f, 0.25886f }
};
float CSkyDome::m_zenithymatrix[ 3 ][ 4 ] = {
{ 0.00275f, -0.00610f, 0.00317f, 0.00000f },
{ -0.04214f, 0.08970f, -0.04153f, 0.00516f },
{ 0.15346f, -0.26756f, 0.06670f, 0.26688f }
};
//******************************************************************************//
float clamp( float const Value, float const Min, float const Max ) {
float value = Value;
if( value < Min ) { value = Min; }
if( value > Max ) { value = Max; }
return value;
}
float interpolate( float const First, float const Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
//******************************************************************************//
CSkyDome::CSkyDome (int const Tesselation) :
m_tesselation( Tesselation ) {
// SetSunPosition( Math3D::vector3(75.0f, 0.0f, 0.0f) );
SetTurbidity( 3.0f );
SetExposure( true, 20.0f );
SetOvercastFactor( 0.05f );
SetGammaCorrection( 2.2f );
Generate();
}
CSkyDome::~CSkyDome() {
}
//******************************************************************************//
void CSkyDome::Generate() {
// radius of dome
float const radius = 1.0f;
float const offset = 0.1f * radius; // horizontal offset, a cheap way to prevent a gap between ground and horizon
// create geometry chunk
int const latitudes = m_tesselation / 2;
int const longitudes = m_tesselation;
for( int i = 0; i < latitudes; ++i ) {
float lat0 = M_PI * ( -0.5f + (float)( i ) / latitudes );
float z0 = std::sin( lat0 );
float zr0 = std::cos( lat0 );
float lat1 = M_PI * ( -0.5f + (float)( i + 1 ) / latitudes );
float z1 = std::sin( lat1 );
float zr1 = std::cos( lat1 );
// quad strip
for( int j = 0; j <= longitudes / 2; ++j ) {
float longitude = 2.0 * M_PI * (float)( j ) / longitudes;
float x = std::cos( longitude );
float y = std::sin( longitude );
m_vertices.emplace_back( float3( x * zr0, y * zr0 - offset, z0 ) * radius );
// m_normals.emplace_back( float3( -x * zr0, -y * zr0, -z0 ) );
m_colours.emplace_back( float3( 0.75f, 0.75f, 0.75f ) );
m_vertices.emplace_back( float3( x * zr1, y * zr1 - offset, z1 ) * radius );
// m_normals.emplace_back( float3( -x * zr1, -y * zr1, -z1 ) );
m_colours.emplace_back( float3( 0.75f, 0.75f, 0.75f ) );
}
}
}
//******************************************************************************//
void CSkyDome::Update( Math3D::vector3 const &Sun ) {
if( true == SetSunPosition( Sun ) ) {
// build colors if there's a change in sun position
RebuildColors();
}
}
// render skydome to screen
void CSkyDome::Render() {
int const latitudes = m_tesselation / 2;
int const longitudes = m_tesselation;
int idx = 0;
for( int i = 0; i < latitudes; ++i ) {
::glBegin( GL_QUAD_STRIP );
for( int j = 0; j <= longitudes / 2; ++j ) {
::glColor3f( m_colours[ idx ].x, m_colours[ idx ].y, m_colours[ idx ].z );
// ::glNormal3f( m_normals[ idx ].x, m_normals[ idx ].y, m_normals[ idx ].z );
::glVertex3f( m_vertices[ idx ].x, m_vertices[ idx ].y, m_vertices[ idx ].z );
++idx;
::glColor3f( m_colours[ idx ].x, m_colours[ idx ].y, m_colours[ idx ].z );
// ::glNormal3f( m_normals[ idx ].x, m_normals[ idx ].y, m_normals[ idx ].z );
::glVertex3f( m_vertices[ idx ].x, m_vertices[ idx ].y, m_vertices[ idx ].z );
++idx;
}
glEnd();
}
}
//******************************************************************************//
bool CSkyDome::SetSunPosition( Math3D::vector3 const &Direction ) {
auto sundirection = SafeNormalize( float3( Direction.x, Direction.y, Direction.z) );
if( sundirection == m_sundirection ) {
return false;
}
m_sundirection = sundirection;
m_thetasun = std::acosf( m_sundirection.y );
m_phisun = std::atan2( m_sundirection.z, m_sundirection.x );
return true;
}
void CSkyDome::SetTurbidity( float const Turbidity ) {
m_turbidity = clamp( Turbidity, 1.0f, 512.0f );
}
void CSkyDome::SetExposure( bool const Linearexposure, float const Expfactor ) {
m_linearexpcontrol = Linearexposure;
m_expfactor = 1.0f / clamp( Expfactor, 1.0f, std::numeric_limits<float>::infinity() );
}
void CSkyDome::SetGammaCorrection( float const Gamma ) {
m_gammacorrection = 1.0f / clamp( Gamma, std::numeric_limits<float>::epsilon(), std::numeric_limits<float>::infinity() );
}
void CSkyDome::SetOvercastFactor( float const Overcast ) {
m_overcast = clamp( Overcast, 0.0f, 1.0f );
}
//******************************************************************************//
void CSkyDome::GetPerez( float *Perez, float Distribution[ 5 ][ 2 ], const float Turbidity ) {
Perez[ 0 ] = Distribution[ 0 ][ 0 ] * Turbidity + Distribution[ 0 ][ 1 ];
Perez[ 1 ] = Distribution[ 1 ][ 0 ] * Turbidity + Distribution[ 1 ][ 1 ];
Perez[ 2 ] = Distribution[ 2 ][ 0 ] * Turbidity + Distribution[ 2 ][ 1 ];
Perez[ 3 ] = Distribution[ 3 ][ 0 ] * Turbidity + Distribution[ 3 ][ 1 ];
Perez[ 4 ] = Distribution[ 4 ][ 0 ] * Turbidity + Distribution[ 4 ][ 1 ];
}
float CSkyDome::GetZenith( float Zenithmatrix[ 3 ][ 4 ], const float Theta, const float Turbidity ) {
const float theta2 = Theta*Theta;
const float theta3 = Theta*theta2;
return ( Zenithmatrix[0][0] * theta3 + Zenithmatrix[0][1] * theta2 + Zenithmatrix[0][2] * Theta + Zenithmatrix[0][3]) * Turbidity * Turbidity +
( Zenithmatrix[1][0] * theta3 + Zenithmatrix[1][1] * theta2 + Zenithmatrix[1][2] * Theta + Zenithmatrix[1][3]) * Turbidity +
( Zenithmatrix[2][0] * theta3 + Zenithmatrix[2][1] * theta2 + Zenithmatrix[2][2] * Theta + Zenithmatrix[2][3]);
}
//******************************************************************************//
float CSkyDome::PerezFunctionO1( float Perezcoeffs[ 5 ], const float Thetasun, const float Zenithval ) {
const float val = ( 1.0f + Perezcoeffs[ 0 ] * std::exp( Perezcoeffs[ 1 ] ) ) *
( 1.0f + Perezcoeffs[ 2 ] * std::exp( Perezcoeffs[ 3 ] * Thetasun ) + Perezcoeffs[ 4 ] * std::pow( std::cos( Thetasun ), 2 ) );
return Zenithval / val;
}
float CSkyDome::PerezFunctionO2( float Perezcoeffs[ 5 ], const float Icostheta, const float Gamma, const float Cosgamma2, const float Zenithval ) {
// iCosTheta = 1.0f / cosf(theta)
// cosGamma2 = SQR( cosf( gamma ) )
return Zenithval * ( 1.0f + Perezcoeffs[ 0 ] * std::exp( Perezcoeffs[ 1 ] * Icostheta ) ) *
( 1.0f + Perezcoeffs[ 2 ] * std::exp( Perezcoeffs[ 3 ] * Gamma ) + Perezcoeffs[ 4 ] * Cosgamma2 );
}
//******************************************************************************//
void CSkyDome::RebuildColors() {
// get zenith luminance
float const chi = ( (4.0f / 9.0f) - (m_turbidity / 120.0f) ) * ( M_PI - (2.0f * m_thetasun) );
float zenithluminance = ( (4.0453f * m_turbidity) - 4.9710f ) * std::tan( chi ) - (0.2155f * m_turbidity) + 2.4192f;
// get x / y zenith
float zenithx = GetZenith( m_zenithxmatrix, m_thetasun, m_turbidity );
float zenithy = GetZenith( m_zenithymatrix, m_thetasun, m_turbidity );
// get perez function parametrs
float perezluminance[5], perezx[5], perezy[5];
GetPerez( perezluminance, m_distributionluminance, m_turbidity );
GetPerez( perezx, m_distributionxcomp, m_turbidity );
GetPerez( perezy, m_distributionycomp, m_turbidity );
// make some precalculation
zenithx = PerezFunctionO1( perezx, m_thetasun, zenithx );
zenithy = PerezFunctionO1( perezy, m_thetasun, zenithy );
zenithluminance = PerezFunctionO1( perezluminance, m_thetasun, zenithluminance );
// start with fresh average for the new pass
float3 averagecolor{ 0.0f, 0.0f, 0.0f };
// trough all vertices
float3 vertex;
float3 color, colorconverter, shiftedcolor;
for ( unsigned int i = 0; i < m_vertices.size(); ++i ) {
// grab it
vertex = SafeNormalize( m_vertices[ i ] );
// angle between sun and vertex
const float gamma = std::acos( DotProduct( vertex, m_sundirection ) );
// warning : major hack!!! .. i had to do something with values under horizon
//vertex.y = Clamp<float>( vertex.y, 0.05f, 1.0f );
if ( vertex.y < 0.05f ) vertex.y = 0.05f;
// from paper:
// const float theta = arccos( vertex.y );
// const float iCosTheta = 1.0f / cosf( theta );
// optimized:
// iCosTheta =
// = 1.0f / cosf( arccos( vertex.y ) );
// = 1.0f / vertex.y;
float const icostheta = 1.0f / vertex.y;
float const cosgamma2 = std::pow( std::cos( gamma ), 2 );
// Compute x,y values
float const x = PerezFunctionO2( perezx, icostheta, gamma, cosgamma2, zenithx );
float const y = PerezFunctionO2( perezy, icostheta, gamma, cosgamma2, zenithy );
// luminance(Y) for clear & overcast sky
float const yclear = PerezFunctionO2( perezluminance, icostheta, gamma, cosgamma2, zenithluminance );
float const yover = ( 1.0f + 2.0f * vertex.y ) / 3.0f;
float const Y = interpolate( yclear, yover, m_overcast );
float const X = (x / y) * Y;
float const Z = ((1.0f - x - y) / y) * Y;
colorconverter = float3( X, Y, Z );
color = XYZtoRGB( colorconverter );
colorconverter = RGBtoHSV(color);
if ( m_linearexpcontrol ) {
// linear scale
colorconverter.z *= m_expfactor;
} else {
// exp scale
colorconverter.z = 1.0f - exp( -m_expfactor * colorconverter.z );
}
// override the hue, based on sun height above the horizon. crude way to deal with model shortcomings
// correction begins when the sun is higher than 10 degrees above the horizon, and fully in effect at 10+15 degrees
auto const degreesabovehorizon = 90.0f - m_thetasun * ( 180.0f / M_PI );
auto const sunbasedphase = clamp( (1.0f / 15.0f) * ( degreesabovehorizon - 10.0f ), 0.0f, 1.0f );
// correction is applied in linear manner from the bottom, becomes fully in effect for vertices with y = 0.50
auto const heightbasedphase = clamp( vertex.y * 2.0f, 0.0f, 1.0f );
// this height-based factor is reduced the farther the sky is up in the sky
float const shiftfactor = clamp( interpolate(heightbasedphase, sunbasedphase, sunbasedphase), 0.0f, 1.0f );
// h = 210 makes for 'typical' sky tone
shiftedcolor = float3( 210.0f, colorconverter.y, colorconverter.z );
shiftedcolor = HSVtoRGB( shiftedcolor );
color = HSVtoRGB(colorconverter);
color = Interpolate( color, shiftedcolor, shiftfactor );
/*
// gamma control
color.x = std::pow( color.x, m_gammacorrection );
color.x = std::pow( color.y, m_gammacorrection );
color.x = std::pow( color.z, m_gammacorrection );
*/
// crude correction for the times where the model breaks (late night)
// TODO: use proper night sky calculation for these times instead
if( ( color.x <= 0.0f )
&& ( color.y <= 0.0f ) ) {
// darken the sky as the sun goes deeper below the horizon
// 15:50:75 is picture-based night sky colour. it may not be accurate but looks 'right enough'
color.z = 0.75f * std::max( color.z + m_sundirection.y, 0.075f );
color.x = 0.20f * color.z;
color.y = 0.65f * color.z;
color = color * ( 1.15f - vertex.y ); // simple gradient, darkening towards the top
}
// save
m_colours[ i ] = color;
averagecolor += color;
}
m_averagecolour = averagecolor / m_vertices.size();
m_averagecolour.x = std::max( m_averagecolour.x, 0.0f );
m_averagecolour.y = std::max( m_averagecolour.y, 0.0f );
m_averagecolour.z = std::max( m_averagecolour.z, 0.0f );
}
//******************************************************************************//

60
skydome.h Normal file
View File

@@ -0,0 +1,60 @@
#pragma once
#include "dumb3d.h"
#include "float3d.h"
// sky gradient based on "A practical analytic model for daylight"
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
class CSkyDome {
public:
CSkyDome( int const Tesselation = 54 );
~CSkyDome();
void Generate();
void RebuildColors();
bool SetSunPosition( Math3D::vector3 const &Direction );
void SetTurbidity( const float Turbidity = 5.0f );
void SetExposure( const bool Linearexposure, const float Expfactor );
void SetOvercastFactor( const float Overcast = 0.0f );
void SetGammaCorrection( const float Gamma = 2.2f );
// update skydome
void Update( Math3D::vector3 const &Sun );
// render skydome to screen
void Render();
// retrieves average colour of the sky dome
float3 GetAverageColor() { return m_averagecolour; }
private:
// shading parametrs
float3 m_sundirection;
float m_thetasun, m_phisun;
float m_turbidity;
bool m_linearexpcontrol;
float m_expfactor;
float m_overcast;
float m_gammacorrection;
float3 m_averagecolour;
// data
int const m_tesselation;
std::vector<float3> m_vertices;
// std::vector<float3> m_normals;
std::vector<float3> m_colours;
static float m_distributionluminance[ 5 ][ 2 ];
static float m_distributionxcomp[ 5 ][ 2 ];
static float m_distributionycomp[ 5 ][ 2 ];
static float m_zenithxmatrix[ 3 ][ 4 ];
static float m_zenithymatrix[ 3 ][ 4 ];
// coloring
void GetPerez( float *Perez, float Distribution[ 5 ][ 2 ], const float Turbidity );
float GetZenith( float Zenithmatrix[ 3 ][ 4 ], const float Theta, const float Turbidity );
float PerezFunctionO1( float Perezcoeffs[ 5 ], const float Thetasun, const float Zenithval );
float PerezFunctionO2( float Perezcoeffs[ 5 ], const float Icostheta, const float Gamma, const float Cosgamma2, const float Zenithval );
};

28
stars.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include "stdafx.h"
#include "stars.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////////////////////
// cStars -- simple starfield model, simulating appearance of starry sky
void
cStars::init() {
m_stars.LoadFromFile( "models\\skydome_stars.t3d", false );
}
void
cStars::render() {
::glPushMatrix();
::glRotatef( m_latitude, 1.0f, 0.0f, 0.0f ); // ustawienie osi OY na północ
::glRotatef( -std::fmod( Global::fTimeAngleDeg, 360.0f ), 0.0f, 1.0f, 0.0f ); // obrót dobowy osi OX
::glPointSize( 2.0f );
m_stars.Render( 1.0 );
::glPointSize( 3.0f );
::glPopMatrix();
}

33
stars.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include "Model3d.h"
//////////////////////////////////////////////////////////////////////////////////////////
// cStars -- simple starfield model, simulating appearance of starry sky
class cStars {
public:
// types:
// methods:
void init();
void render();
// constructors:
// deconstructor:
// members:
private:
// types:
// methods:
// members:
float m_longitude{ 19.0f }; // geograpic coordinates hardcoded roughly to Poland location, for the time being
float m_latitude{ 52.0f };
TModel3d m_stars;
};

318
sun.cpp Normal file
View File

@@ -0,0 +1,318 @@
#include "stdafx.h"
#include "sun.h"
#include "globals.h"
#include "mtable.h"
//////////////////////////////////////////////////////////////////////////////////////////
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
cSun::cSun() {
setLocation( 19.00f, 52.00f ); // default location roughly in centre of Poland
m_observer.press = 1013.0; // surface pressure, millibars
m_observer.temp = 15.0; // ambient dry-bulb temperature, degrees C
TIME_ZONE_INFORMATION timezoneinfo; // TODO: timezone dependant on geographic location
::GetTimeZoneInformation( &timezoneinfo );
m_observer.timezone = -timezoneinfo.Bias / 60.0f;
}
cSun::~cSun() { gluDeleteQuadric( sunsphere ); }
void
cSun::init() {
sunsphere = gluNewQuadric();
gluQuadricNormals( sunsphere, GLU_SMOOTH );
}
void
cSun::update() {
move();
Math3D::vector3 position( 0.0f, 0.0f, -2000.0f );
position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) );
position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) );
m_position = position;
}
void
cSun::render() {
/*
glLightfv(GL_LIGHT0, GL_POSITION, position.getVector() ); // sun
GLfloat LightPosition[]= { 10.0f, 50.0f, -5.0f, 1.0f }; // ambient
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition );
*/
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glColor4f( 255.0f/255.0f, 242.0f/255.0f, 231.0f/255.0f, 1.f );
// debug line to locate the sun easier
Math3D::vector3 position = m_position;
glBegin( GL_LINES );
glVertex3f( position.x, position.y, position.z );
glVertex3f( position.x, 0.0f, position.z );
glEnd();
glPushMatrix();
glTranslatef( position.x, position.y, position.z );
// radius is a result of scaling true distance down to 2km -- it's scaled by equal ratio
gluSphere( sunsphere, (float)(m_body.distance * 9.359157), 12, 12 );
glPopMatrix();
glEnable(GL_FOG);
glEnable(GL_LIGHTING);
}
Math3D::vector3
cSun::getDirection() {
Math3D::vector3 position( 0.f, 0.f, -1.f );
position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) );
position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) );
position.Normalize();
return position;
}
float
cSun::getAngle() {
return (float)m_body.elevref;
}
float cSun::getIntensity() {
irradiance();
return (float)( m_body.etr/ 1399.0 ); // arbitrary scaling factor taken from etrn value
}
void cSun::setLocation( float const Longitude, float const Latitude ) {
// convert fraction from geographical base of 6o minutes
m_observer.longitude = (int)Longitude + (Longitude - (int)(Longitude)) * 100.0 / 60.0;
m_observer.latitude = (int)Latitude + (Latitude - (int)(Latitude)) * 100.0 / 60.0 ;
}
void cSun::setTemperature( float const Temperature ) {
m_observer.temp = Temperature;
}
void cSun::setPressure( float const Pressure ) {
m_observer.press = Pressure;
}
void cSun::move() {
static double degrad = 57.295779513; // converts from radians to degrees
static double raddeg = 0.0174532925; // converts from degrees to radians
SYSTEMTIME localtime; // time for the calculation
time( &localtime );
double ut = localtime.wHour
+ localtime.wMinute / 60.0 // too low resolution, noticeable skips
+ localtime.wSecond / 3600.0; // good enough in normal circumstances
/*
+ localtime.wMilliseconds / 3600000.0; // for really smooth movement
*/
double daynumber = 367 * localtime.wYear
- 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) /12 ) / 4
+ 275 * localtime.wMonth / 9
+ localtime.wDay
- 730530
+ (ut / 24.0);
// Universal Coordinated (Greenwich standard) time
m_observer.utime = ut * 3600.0;
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
// mean longitude
m_body.mnlong = 280.460 + 0.9856474 * daynumber;
m_body.mnlong -= 360.0 * (int) ( m_body.mnlong / 360.0 ); // clamp the range to 0-360
if( m_body.mnlong < 0.0 ) m_body.mnlong += 360.0;
// mean anomaly
m_body.mnanom = 357.528 + 0.9856003 * daynumber;
m_body.mnanom -= 360.0 * (int) ( m_body.mnanom / 360.0 ); // clamp the range to 0-360
if( m_body.mnanom < 0.0 ) m_body.mnanom += 360.0;
// ecliptic longitude
m_body.eclong = m_body.mnlong
+ 1.915 * sin( m_body.mnanom * raddeg )
+ 0.020 * sin ( 2.0 * m_body.mnanom * raddeg );
m_body.eclong -= 360.0 * (int)( m_body.eclong / 360.0 );
if( m_body.eclong < 0.0 ) m_body.eclong += 360.0; // clamp the range to 0-360
// obliquity of the ecliptic
m_body.ecobli = 23.439 - 4.0e-07 * daynumber;
// declination
m_body.declin = degrad * asin( sin (m_body.ecobli * raddeg) * sin (m_body.eclong * raddeg) );
// right ascension
double top = cos ( raddeg * m_body.ecobli ) * sin ( raddeg * m_body.eclong );
double bottom = cos ( raddeg * m_body.eclong );
m_body.rascen = degrad * atan2( top, bottom );
if( m_body.rascen < 0.0 ) m_body.rascen += 360.0; // (make it a positive angle)
// Greenwich mean sidereal time
m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime;
m_observer.gmst -= 24.0 * (int)( m_observer.gmst / 24.0 );
if( m_observer.gmst < 0.0 ) m_observer.gmst += 24.0;
// local mean sidereal time
m_observer.lmst = m_observer.gmst * 15.0 + m_observer.longitude;
m_observer.lmst -= 360.0 * (int)( m_observer.lmst / 360.0 );
if( m_observer.lmst < 0.0 ) m_observer.lmst += 360.0;
// hour angle
m_body.hrang = m_observer.lmst - m_body.rascen;
if( m_body.hrang < -180.0 ) m_body.hrang += 360.0; // (force it between -180 and 180 degrees)
else if( m_body.hrang > 180.0 ) m_body.hrang -= 360.0;
double cz; // cosine of the solar zenith angle
double tdatcd = cos( raddeg * m_body.declin );
double tdatch = cos( raddeg * m_body.hrang );
double tdatcl = cos( raddeg * m_observer.latitude );
double tdatsd = sin( raddeg * m_body.declin );
double tdatsl = sin( raddeg * m_observer.latitude );
cz = tdatsd * tdatsl + tdatcd * tdatcl * tdatch;
// (watch out for the roundoff errors)
if( fabs (cz) > 1.0 ) { cz >= 0.0 ? cz = 1.0 : cz = -1.0; }
m_body.zenetr = acos( cz ) * degrad;
m_body.elevetr = 90.0 - m_body.zenetr;
refract();
// additional calculations for proper object sizing.
// orbit eccentricity
double e = 0.016709 - 1.151e-9 * daynumber;
// eccentric anomaly
double E = m_body.mnanom + e * degrad * sin(m_body.mnanom) * ( 1.0 + e * cos(m_body.mnanom) );
double xv = cos(E) - e;
double yv = sqrt(1.0 - e*e) * sin(E);
m_body.distance = sqrt( xv*xv + yv*yv );
}
void cSun::refract() {
static double raddeg = 0.0174532925; // converts from degrees to radians
double prestemp; // temporary pressure/temperature correction
double refcor; // temporary refraction correction
double tanelev; // tangent of the solar elevation angle
// if the sun is near zenith, the algorithm bombs; refraction near 0.
if( m_body.elevetr > 85.0 )
refcor = 0.0;
else {
tanelev = tan( raddeg * m_body.elevetr );
if( m_body.elevetr >= 5.0 )
refcor = 58.1 / tanelev
- 0.07 / pow( tanelev, 3 )
+ 0.000086 / pow( tanelev, 5 );
else if( m_body.elevetr >= -0.575 )
refcor = 1735.0
+ m_body.elevetr * ( -518.2 + m_body.elevetr *
( 103.4 + m_body.elevetr * ( -12.79 + m_body.elevetr * 0.711 ) ) );
else
refcor = -20.774 / tanelev;
prestemp = ( m_observer.press * 283.0 ) / ( 1013.0 * ( 273.0 + m_observer.temp ) );
refcor *= prestemp / 3600.0;
}
// refracted solar elevation angle
m_body.elevref = m_body.elevetr + refcor;
// refracted solar zenith angle
m_body.zenref = 90.0 - m_body.elevref;
}
void cSun::irradiance() {
static double degrad = 57.295779513; // converts from radians to degrees
static double raddeg = 0.0174532925; // converts from degrees to radians
SYSTEMTIME localtime; // time for the calculation
time( &localtime );
m_body.dayang = ( yearday( localtime.wDay, localtime.wMonth, localtime.wYear ) - 1 ) * 360.0 / 365.0;
double sd = sin( raddeg * m_body.dayang ); // sine of the day angle
double cd = cos( raddeg * m_body.dayang ); // cosine of the day angle or delination
m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd;
double d2 = 2.0 * m_body.dayang;
double c2 = cos( raddeg * d2 );
double s2 = sin( raddeg * 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 );
if( m_body.coszen > 0.0 ) {
m_body.etrn = solcon * m_body.erv;
m_body.etr = m_body.etrn * m_body.coszen;
}
else {
m_body.etrn = 0.0;
m_body.etr = 0.0;
}
}
int cSun::yearday( int Day, const int Month, const int Year ) {
char daytab[ 2 ][ 13 ] = {
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
int i, leap;
leap = ( Year%4 == 0 ) && ( Year%100 != 0 ) || ( Year%400 == 0 );
for( i = 1; i < Month; ++i )
Day += daytab[ leap ][ i ];
return Day;
}
void cSun::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday ) {
WORD daytab[ 2 ][ 13 ] = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int leap = ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 );
WORD idx = 1;
while( (idx < 13) && ( Yearday <= daytab[ leap ][ idx ] )) {
++idx;
}
Month = idx + 1;
Day = Yearday - daytab[ leap ][ idx ];
}
// obtains current time for calculations
void
cSun::time( SYSTEMTIME *Time ) {
::GetLocalTime( Time );
// NOTE: we're currently using local time to determine day/month/year
if( Global::fMoveLight > 0.0 ) {
// TODO: enter scenario-defined day/month/year instead.
daymonth( Time->wDay, Time->wMonth, Time->wYear, static_cast<WORD>(Global::fMoveLight) );
}
Time->wHour = GlobalTime->hh;
Time->wMinute = GlobalTime->mm;
Time->wSecond = std::floor( GlobalTime->mr );
}

101
sun.h Normal file
View File

@@ -0,0 +1,101 @@
#pragma once
#include "windows.h"
#include "opengl/glew.h"
#include "opengl/wglew.h"
#include "dumb3d.h"
//////////////////////////////////////////////////////////////////////////////////////////
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
// given current weather, time and geographic location.
class cSun {
public:
// types:
// methods:
void init();
void update();
void render();
// returns location of the sun in the 3d scene
Math3D::vector3 getPosition() { return m_position; }
// returns vector pointing at the sun
Math3D::vector3 getDirection();
// returns current elevation above horizon
float getAngle();
// returns current intensity of the sun
float getIntensity();
// sets current geographic location
void setLocation( float const Longitude, float const Latitude );
// sets ambient temperature in degrees C.
void setTemperature( float const Temperature );
// sets surface pressure in milibars
void setPressure( float const Pressure );
// constructors:
cSun();
// deconstructor:
~cSun();
// members:
protected:
// types:
// methods:
// calculates sun position on the sky given specified time and location
void move();
// calculates position adjustment due to refraction
void refract();
// calculates light intensity at current moment
void irradiance();
// calculates day of year from given date
int yearday( int Day, int const Month, int const Year );
// calculates day and month from given day of year
void daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yearday );
// obtains current time for calculations
void time( SYSTEMTIME *Time );
// members:
GLUquadricObj *sunsphere; // temporary handler for sun positioning test
struct celestialbody { // main planet parameters
double dayang; // day angle (daynum*360/year-length) degrees
double mnlong; // mean longitude, degrees
double mnanom; // mean anomaly, degrees
double eclong; // ecliptic longitude, degrees.
double ecobli; // obliquity of ecliptic.
double declin; // declination--zenith angle of solar noon at equator, degrees NORTH.
double rascen; // right ascension, degrees
double hrang; // hour angle--hour of sun from solar noon, degrees WEST
double zenetr; // solar zenith angle, no atmospheric correction (= ETR)
double zenref; // solar zenith angle, deg. from zenith, refracted
double coszen; // cosine of refraction corrected solar zenith angle
double elevetr; // solar elevation, no atmospheric correction (= ETR)
double elevref; // solar elevation angle, deg. from horizon, refracted.
double distance; // distance from earth in AUs
double erv; // earth radius vector (multiplied to solar constant)
double etr; // extraterrestrial (top-of-atmosphere) W/sq m global horizontal solar irradiance
double etrn; // extraterrestrial (top-of-atmosphere) W/sq m direct normal solar irradiance
};
struct observer { // weather, time and position data in observer's location
double latitude; // latitude, degrees north (south negative)
double longitude; // longitude, degrees east (west negative)
double utime; // universal (Greenwich) standard time
double timezone; // time zone, east (west negative). USA: Mountain = -7, Central = -6, etc.
double gmst; // Greenwich mean sidereal time, hours
double lmst; // local mean sidereal time, degrees
double temp; // ambient dry-bulb temperature, degrees C, used for refraction correction
double press; // surface pressure, millibars, used for refraction correction and ampress
};
celestialbody m_body;
observer m_observer;
Math3D::vector3 m_position;
};