mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-24 21:27:37 +02:00
Merge remote-tracking branch 'tmj-fstate/mover_in_c++' into mover_in_c++
This commit is contained in:
107
Driver.cpp
107
Driver.cpp
@@ -82,8 +82,8 @@ Tutaj łączymy teorię z praktyką - tu nic nie działa i nikt nie wie dlaczego
|
||||
// stałe
|
||||
const double EasyReactionTime = 0.5; //[s] przebłyski świadomości dla zwykłej jazdy
|
||||
const double HardReactionTime = 0.2;
|
||||
const double EasyAcceleration = 0.5; //[m/ss]
|
||||
const double HardAcceleration = 0.9;
|
||||
const double EasyAcceleration = 0.85; //[m/ss]
|
||||
const double HardAcceleration = 9.81;
|
||||
const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu
|
||||
bool WriteLogFlag = false;
|
||||
|
||||
@@ -230,9 +230,7 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
|
||||
if( fDist < 50.0 ) {
|
||||
// old sceneries use trick of placing 'helper' semaphores underground, which can lead to vehicles running over them instead of stopping in front of them
|
||||
// to account for it at short distances we redo distance calculation on 2d plane
|
||||
fDist = glm::dot(
|
||||
glm::vec3( v.x, 0.0, v.z ),
|
||||
glm::vec3( dir->x, 0.0, dir->z ) );
|
||||
fDist = glm::length( glm::vec3( v.x, 0.0, v.z ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -452,7 +450,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
||||
TEvent *pEvent{ nullptr };
|
||||
double fLastDir{ 0.0 };
|
||||
|
||||
if (iTableDirection != iDirection) {
|
||||
if (iTableDirection != iDirection ) {
|
||||
// jeśli zmiana kierunku, zaczynamy od toru ze wskazanym pojazdem
|
||||
iTableDirection = iDirection; // ustalenie w jakim kierunku jest wypełniana tabelka względem pojazdu
|
||||
pTrack = pVehicle->RaTrackGet(); // odcinek, na którym stoi
|
||||
@@ -470,6 +468,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
||||
SemNextStopIndex = -1;
|
||||
}
|
||||
else {
|
||||
if( iTableDirection == 0 ) { return; }
|
||||
// kontynuacja skanowania od ostatnio sprawdzonego toru (w ostatniej pozycji zawsze jest tor)
|
||||
if( ( SemNextStopIndex != -1 )
|
||||
&& ( sSpeedTable[SemNextStopIndex].fVelNext < 1.0 ) ) {
|
||||
@@ -503,6 +502,11 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
||||
pTrack->Length() );
|
||||
}
|
||||
|
||||
if( iTableDirection == 0 ) {
|
||||
// don't bother
|
||||
return;
|
||||
}
|
||||
|
||||
if( fCurrentDistance >= fDistance ) {
|
||||
// all done
|
||||
return;
|
||||
@@ -1666,14 +1670,20 @@ void TController::AutoRewident()
|
||||
}
|
||||
};
|
||||
|
||||
int TController::CheckDirection() {
|
||||
|
||||
int d = mvOccupied->DirAbsolute; // który sprzęg jest z przodu
|
||||
if( !d ) // jeśli nie ma ustalonego kierunku
|
||||
d = mvOccupied->CabNo; // to jedziemy wg aktualnej kabiny
|
||||
iDirection = d; // ustalenie kierunku jazdy (powinno zrobić PrepareEngine?)
|
||||
return d;
|
||||
}
|
||||
|
||||
bool TController::CheckVehicles(TOrders user)
|
||||
{ // sprawdzenie stanu posiadanych pojazdów w składzie i zapalenie świateł
|
||||
TDynamicObject *p; // roboczy wskaźnik na pojazd
|
||||
iVehicles = 0; // ilość pojazdów w składzie
|
||||
int d = mvOccupied->DirAbsolute; // który sprzęg jest z przodu
|
||||
if (!d) // jeśli nie ma ustalonego kierunku
|
||||
d = mvOccupied->CabNo; // to jedziemy wg aktualnej kabiny
|
||||
iDirection = d; // ustalenie kierunku jazdy (powinno zrobić PrepareEngine?)
|
||||
int d = CheckDirection();
|
||||
d = d >= 0 ? 0 : 1; // kierunek szukania czoła (numer sprzęgu)
|
||||
pVehicles[0] = p = pVehicle->FirstFind(d); // pojazd na czele składu
|
||||
// liczenie pojazdów w składzie i ustalenie parametrów
|
||||
@@ -2060,20 +2070,22 @@ bool TController::PrepareEngine()
|
||||
mvOccupied->BatterySwitch(true);
|
||||
if (mvControlling->EnginePowerSource.SourceType == CurrentCollector)
|
||||
{ // jeśli silnikowy jest pantografującym
|
||||
if (mvControlling->PantPress > 4.3)
|
||||
{ // jeżeli jest wystarczające ciśnienie w pantografach
|
||||
mvControlling->PantFront( true );
|
||||
mvControlling->PantRear( true );
|
||||
if (mvControlling->PantPress < 4.2) {
|
||||
// załączenie małej sprężarki
|
||||
if( mvControlling->TrainType != dt_EZT ) {
|
||||
// odłączenie zbiornika głównego, bo z nim nie da rady napompować
|
||||
mvControlling->bPantKurek3 = false;
|
||||
}
|
||||
mvControlling->PantCompFlag = true; // załączenie sprężarki pantografów
|
||||
}
|
||||
else {
|
||||
// jeżeli jest wystarczające ciśnienie w pantografach
|
||||
if ((!mvControlling->bPantKurek3) ||
|
||||
(mvControlling->PantPress <=
|
||||
mvControlling->ScndPipePress)) // kurek przełączony albo główna już pompuje
|
||||
mvControlling->PantCompFlag = false; // sprężarkę pantografów można już wyłączyć
|
||||
mvControlling->PantFront(true);
|
||||
mvControlling->PantRear(true);
|
||||
}
|
||||
else if (mvControlling->PantPress < 4.2) //żeby nie załączał zaraz po przekroczeniu 4.0
|
||||
{ // załączenie małej sprężarki
|
||||
mvControlling->bPantKurek3 =
|
||||
false; // odłączenie zbiornika głównego, bo z nim nie da rady napompować
|
||||
mvControlling->PantCompFlag = true; // załączenie sprężarki pantografów
|
||||
}
|
||||
}
|
||||
// if (mvOccupied->TrainType==dt_EZT)
|
||||
@@ -2354,11 +2366,19 @@ bool TController::IncSpeed()
|
||||
if (tsGuardSignal->GetStatus() & DSBSTATUS_PLAYING) // jeśli gada, to nie jedziemy
|
||||
return false;
|
||||
bool OK = true;
|
||||
if ( ( iDrivigFlags & moveDoorOpened )
|
||||
&& ( VelDesired > 0.0 ) ) // to prevent door shuffle on stop
|
||||
Doors(false); // zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime)
|
||||
if (fActionTime < 0.0) // gdy jest nakaz poczekać z jazdą, to nie ruszać
|
||||
if( ( iDrivigFlags & moveDoorOpened )
|
||||
&& ( VelDesired > 0.0 ) ) { // to prevent door shuffle on stop
|
||||
// zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime)
|
||||
Doors( false );
|
||||
}
|
||||
if( fActionTime < 0.0 ) {
|
||||
// gdy jest nakaz poczekać z jazdą, to nie ruszać
|
||||
return false;
|
||||
}
|
||||
if( true == mvOccupied->DepartureSignal ) {
|
||||
// shut off departure warning
|
||||
mvOccupied->DepartureSignal = false;
|
||||
}
|
||||
if (mvControlling->SlippingWheels)
|
||||
return false; // jak poślizg, to nie przyspieszamy
|
||||
switch (mvOccupied->EngineType)
|
||||
@@ -2530,8 +2550,6 @@ void TController::SpeedSet()
|
||||
switch (mvOccupied->EngineType)
|
||||
{
|
||||
case None: // McZapkie-041003: wagon sterowniczy
|
||||
if (fActionTime >= -1.0)
|
||||
mvOccupied->DepartureSignal = false; // trochę niech pobuczy, zanim pojedzie
|
||||
if (mvControlling->MainCtrlPosNo > 0)
|
||||
{ // jeśli ma czym kręcić
|
||||
// TODO: sprawdzanie innego czlonu //if (!FuseFlagCheck())
|
||||
@@ -2716,17 +2734,24 @@ void TController::Doors(bool what)
|
||||
{ // zamykanie
|
||||
if (mvOccupied->DoorOpenCtrl == 1)
|
||||
{ // jeśli drzwi sterowane z kabiny
|
||||
if (AIControllFlag)
|
||||
if (mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened)
|
||||
{ // AI zamyka drzwi przed odjazdem
|
||||
if (mvOccupied->DoorClosureWarning)
|
||||
if( AIControllFlag ) {
|
||||
if( mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened ) { // AI zamyka drzwi przed odjazdem
|
||||
if( ( true == mvOccupied->DoorClosureWarning )
|
||||
&& ( false == mvOccupied->DepartureSignal )
|
||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||
mvOccupied->DepartureSignal = true; // załącenie bzyczka
|
||||
mvOccupied->DoorLeft(false); // zamykanie drzwi
|
||||
mvOccupied->DoorRight(false);
|
||||
fActionTime = -3.0 - 0.1 * Random( 10 ); // 3-4 second wait
|
||||
}
|
||||
if( fActionTime > -0.5 ) {
|
||||
// Ra: trzeba by ustawić jakiś czas oczekiwania na zamknięcie się drzwi
|
||||
fActionTime = -1.5 - 0.1 * Random(10); // czekanie sekundę, może trochę dłużej
|
||||
iDrivigFlags &= ~moveDoorOpened; // nie wykonywać drugi raz
|
||||
mvOccupied->DoorLeft( false ); // zamykanie drzwi
|
||||
mvOccupied->DoorRight( false );
|
||||
iDrivigFlags &= ~moveDoorOpened;
|
||||
// 1.5-2.5 sec wait, +potentially 0.5 remaining
|
||||
fActionTime = -1.5 - 0.1 * Random( 10 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // jeśli nie, to zamykanie w składzie wagonowym
|
||||
@@ -2738,7 +2763,7 @@ void TController::Doors(bool what)
|
||||
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
|
||||
}
|
||||
// WaitingSet(5); //10 sekund tu to za długo, opóźnia odjazd o pół minuty
|
||||
fActionTime = -1.5 - 0.1 * Random(10); // czekanie sekundę, może trochę dłużej
|
||||
fActionTime = -3.0 - 0.1 * Random(10); // czekanie sekundę, może trochę dłużej
|
||||
iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz
|
||||
}
|
||||
}
|
||||
@@ -3263,18 +3288,12 @@ bool TController::UpdateSituation(double dt)
|
||||
{
|
||||
if (mvControlling->EnginePowerSource.SourceType == CurrentCollector)
|
||||
{
|
||||
if (mvOccupied->ScndPipePress > 4.3) // gdy główna sprężarka bezpiecznie nabije
|
||||
// ciśnienie
|
||||
mvControlling->bPantKurek3 =
|
||||
true; // to można przestawić kurek na zasilanie pantografów z głównej pneumatyki
|
||||
if (mvOccupied->ScndPipePress > 4.3) // gdy główna sprężarka bezpiecznie nabije ciśnienie
|
||||
mvControlling->bPantKurek3 = true; // to można przestawić kurek na zasilanie pantografów z głównej pneumatyki
|
||||
fVoltage =
|
||||
0.5 * (fVoltage +
|
||||
fabs(mvControlling->RunningTraction.TractionVoltage)); // uśrednione napięcie
|
||||
// sieci: przy spadku
|
||||
// poniżej wartości
|
||||
// minimalnej opóźnić
|
||||
// rozruch o losowy
|
||||
// czas
|
||||
// sieci: przy spadku poniżej wartości minimalnej opóźnić rozruch o losowy czas
|
||||
if (fVoltage < mvControlling->EnginePowerSource.CollectorParameters
|
||||
.MinV) // gdy rozłączenie WS z powodu niskiego napięcia
|
||||
if (fActionTime >= 0) // jeśli czas oczekiwania nie został ustawiony
|
||||
|
||||
12
Driver.h
12
Driver.h
@@ -320,9 +320,11 @@ class TController
|
||||
// procedury dotyczace rozkazow dla maszynisty
|
||||
void SetVelocity(double NewVel, double NewVelNext,
|
||||
TStopReason r = stopNone); // uaktualnia informacje o prędkości
|
||||
/*
|
||||
bool SetProximityVelocity(
|
||||
double NewDist,
|
||||
double NewVelNext); // uaktualnia informacje o prędkości przy nastepnym semaforze
|
||||
*/
|
||||
public:
|
||||
void JumpToNextOrder();
|
||||
void JumpToFirstOrder();
|
||||
@@ -331,6 +333,7 @@ class TController
|
||||
inline TOrders OrderCurrentGet();
|
||||
inline TOrders OrderNextGet();
|
||||
bool CheckVehicles(TOrders user = Wait_for_orders);
|
||||
int CheckDirection();
|
||||
|
||||
private:
|
||||
void CloseLog();
|
||||
@@ -351,21 +354,22 @@ class TController
|
||||
void DirectionForward(bool forward);
|
||||
int OrderDirectionChange(int newdir, TMoverParameters *Vehicle);
|
||||
void Lights(int head, int rear);
|
||||
double Distance(vector3 &p1, vector3 &n, vector3 &p2);
|
||||
// double Distance(vector3 &p1, vector3 &n, vector3 &p2);
|
||||
|
||||
private: // Ra: metody obsługujące skanowanie toru
|
||||
TEvent *CheckTrackEvent(double fDirection, TTrack *Track);
|
||||
bool TableCheckEvent(TEvent *e);
|
||||
// bool TableCheckEvent(TEvent *e);
|
||||
bool TableAddNew();
|
||||
bool TableNotFound(TEvent const *Event) const;
|
||||
void TableClear();
|
||||
TEvent *TableCheckTrackEvent(double fDirection, TTrack *Track);
|
||||
// TEvent *TableCheckTrackEvent(double fDirection, TTrack *Track);
|
||||
void TableTraceRoute(double fDistance, TDynamicObject *pVehicle = NULL);
|
||||
void TableCheck(double fDistance);
|
||||
TCommandType TableUpdate(double &fVelDes, double &fDist, double &fNext, double &fAcc);
|
||||
void TablePurger();
|
||||
public:
|
||||
std::size_t TableSize() const { return sSpeedTable.size(); }
|
||||
void TableClear();
|
||||
int TableDirection() { return iTableDirection; }
|
||||
|
||||
private: // Ra: stare funkcje skanujące, używane do szukania sygnalizatora z tyłu
|
||||
bool BackwardTrackBusy(TTrack *Track);
|
||||
|
||||
14
DynObj.cpp
14
DynObj.cpp
@@ -2458,14 +2458,14 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
// opuszczenie pantografów przy niskim ciśnieniu
|
||||
/*
|
||||
// NOTE: disabled, the pantographs drop by themseleves when the pantograph tank pressure gets low enough
|
||||
MoverParameters->PantFront( false, ( MoverParameters->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
MoverParameters->PantRear( false, ( MoverParameters->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
MoverParameters->PantFront( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
MoverParameters->PantRear( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
*/
|
||||
if( MoverParameters->TrainType != dt_EZT ) {
|
||||
// pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage
|
||||
if( MoverParameters->GetTrainsetVoltage() < 0.5 * MoverParameters->EnginePowerSource.MaxVoltage ) {
|
||||
// TODO: check whether line breaker should be open EMU-wide
|
||||
MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2473,7 +2473,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
// and prevents their activation until pressure switch is set again
|
||||
MoverParameters->PantPressLockActive = true;
|
||||
// TODO: separate 'heating allowed' from actual heating flag, so we can disable it here without messing up heating toggle
|
||||
MoverParameters->ConverterSwitch( false, command_range::unit );
|
||||
MoverParameters->ConverterSwitch( false, range::unit );
|
||||
}
|
||||
// mark the pressure switch as spent
|
||||
MoverParameters->PantPressSwitchActive = false;
|
||||
@@ -2936,7 +2936,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
&& ( MoverParameters->EngineType != DieselEngine )
|
||||
&& ( MoverParameters->EngineType != WheelsDriven ) )
|
||||
{ // jeśli bateria wyłączona, a nie diesel ani drezyna reczna
|
||||
if( MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? command_range::unit : command_range::local ) ) ) {
|
||||
if( MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) ) ) {
|
||||
// wyłączyć zasilanie
|
||||
// NOTE: we turn off entire EMU, but only the affected unit for other multi-unit consists
|
||||
MoverParameters->EventFlag = true;
|
||||
@@ -2945,8 +2945,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
// TODO: have this dependant on .fiz-driven flag
|
||||
// NOTE: moved to pantspeed calculation part a little later in the function. all remarks and todo still apply
|
||||
/*
|
||||
MoverParameters->PantFront( false, ( MoverParameters->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
MoverParameters->PantRear( false, ( MoverParameters->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
MoverParameters->PantFront( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
MoverParameters->PantRear( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
40
EU07.cpp
40
EU07.cpp
@@ -52,6 +52,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
|
||||
#pragma comment( lib, "setupapi.lib" )
|
||||
#pragma comment( lib, "python27.lib" )
|
||||
#pragma comment (lib, "dbghelp.lib")
|
||||
#pragma comment (lib, "version.lib")
|
||||
#ifdef CAN_I_HAS_LIBPNG
|
||||
#pragma comment (lib, "libpng16.lib")
|
||||
#endif
|
||||
@@ -224,12 +225,49 @@ int main(int argc, char *argv[])
|
||||
AllocConsole();
|
||||
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), FOREGROUND_GREEN );
|
||||
}
|
||||
|
||||
/*
|
||||
std::string executable( argv[ 0 ] ); auto const pathend = executable.rfind( '\\' );
|
||||
Global::ExecutableName =
|
||||
( pathend != std::string::npos ?
|
||||
executable.substr( executable.rfind( '\\' ) + 1 ) :
|
||||
executable );
|
||||
*/
|
||||
// retrieve product version from the file's version data table
|
||||
{
|
||||
auto const fileversionsize = ::GetFileVersionInfoSize( argv[ 0 ], NULL );
|
||||
std::vector<BYTE>fileversiondata; fileversiondata.resize( fileversionsize );
|
||||
if( ::GetFileVersionInfo( argv[ 0 ], NULL, fileversionsize, fileversiondata.data() ) ) {
|
||||
|
||||
struct lang_codepage {
|
||||
WORD language;
|
||||
WORD codepage;
|
||||
} *langcodepage;
|
||||
UINT datasize;
|
||||
|
||||
::VerQueryValue(
|
||||
fileversiondata.data(),
|
||||
TEXT( "\\VarFileInfo\\Translation" ),
|
||||
(LPVOID*)&langcodepage,
|
||||
&datasize );
|
||||
|
||||
std::string subblock; subblock.resize( 50 );
|
||||
::StringCchPrintf(
|
||||
&subblock[0], subblock.size(),
|
||||
TEXT( "\\StringFileInfo\\%04x%04x\\ProductVersion" ),
|
||||
langcodepage->language,
|
||||
langcodepage->codepage );
|
||||
|
||||
VOID *stringdata;
|
||||
if( ::VerQueryValue(
|
||||
fileversiondata.data(),
|
||||
subblock.data(),
|
||||
&stringdata,
|
||||
&datasize ) ) {
|
||||
|
||||
Global::asVersion = std::string( reinterpret_cast<char*>(stringdata) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
|
||||
@@ -32,8 +32,7 @@ std::string Global::AppName{ "EU07" };
|
||||
std::string Global::asCurrentSceneryPath = "scenery/";
|
||||
std::string Global::asCurrentTexturePath = std::string(szTexturePath);
|
||||
std::string Global::asCurrentDynamicPath = "";
|
||||
int Global::iSlowMotion =
|
||||
0; // info o malym FPS: 0-OK, 1-wyłączyć multisampling, 3-promień 1.5km, 7-1km
|
||||
int Global::iSlowMotion = 0; // info o malym FPS: 0-OK, 1-wyłączyć multisampling, 3-promień 1.5km, 7-1km
|
||||
TDynamicObject *Global::changeDynObj = NULL; // info o zmianie pojazdu
|
||||
double Global::ABuDebug = 0;
|
||||
std::string Global::asSky = "1";
|
||||
@@ -48,9 +47,7 @@ GLFWwindow *Global::window;
|
||||
bool Global::shiftState;
|
||||
bool Global::ctrlState;
|
||||
int Global::iCameraLast = -1;
|
||||
std::string Global::asRelease = "16.0.1172.482";
|
||||
std::string Global::asVersion = "Compilation 2017-03-19, release " + Global::asRelease; // tutaj, bo wysyłany
|
||||
std::string Global::ExecutableName;
|
||||
std::string Global::asVersion = "couldn't retrieve version string";
|
||||
int Global::iTextMode = 0; // tryb pracy wyświetlacza tekstowego
|
||||
int Global::iScreenMode[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // numer ekranu wyświetlacza tekstowego
|
||||
double Global::fSunDeclination = 0.0; // deklinacja Słońca
|
||||
|
||||
@@ -266,9 +266,7 @@ class Global
|
||||
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
|
||||
static std::string ExecutableName;
|
||||
static GLint iMaxTextureSize; // maksymalny rozmiar tekstury
|
||||
static int iTextMode; // tryb pracy wyświetlacza tekstowego
|
||||
static int iScreenMode[12]; // numer ekranu wyświetlacza tekstowego
|
||||
|
||||
902
Ground.cpp
902
Ground.cpp
File diff suppressed because it is too large
Load Diff
58
Ground.h
58
Ground.h
@@ -97,12 +97,13 @@ struct TGroundVertex
|
||||
}
|
||||
};
|
||||
|
||||
class TSubRect; // sektor (aktualnie 200m×200m, ale może być zmieniony)
|
||||
|
||||
class TGroundNode : public Resource
|
||||
{ // obiekt scenerii
|
||||
private:
|
||||
public:
|
||||
|
||||
friend class opengl_renderer;
|
||||
|
||||
private:
|
||||
public:
|
||||
TGroundNodeType iType; // typ obiektu
|
||||
union
|
||||
{ // Ra: wskażniki zależne od typu - zrobić klasy dziedziczone zamiast
|
||||
@@ -130,12 +131,7 @@ class TGroundNode : public Resource
|
||||
};
|
||||
vector3 pCenter; // współrzędne środka do przydzielenia sektora
|
||||
|
||||
union
|
||||
{
|
||||
// double fAngle; //kąt obrotu dla modelu
|
||||
double fLineThickness; // McZapkie-120702: grubosc linii
|
||||
// int Status; //McZapkie-170303: status dzwieku
|
||||
};
|
||||
double fLineThickness; // McZapkie-120702: grubosc linii
|
||||
double fSquareRadius; // kwadrat widoczności do
|
||||
double fSquareMinRadius; // kwadrat widoczności od
|
||||
// TGroundNode *nMeshGroup; //Ra: obiekt grupujący trójkąty w TSubRect dla tekstury
|
||||
@@ -174,12 +170,8 @@ class TGroundNode : public Resource
|
||||
void Release();
|
||||
|
||||
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
|
||||
void RenderDL(); // renderowanie nieprzezroczystych w Display Lists
|
||||
void RenderAlphaDL(); // renderowanie przezroczystych w Display Lists
|
||||
// (McZapkie-131202)
|
||||
void RaRenderVBO(); // renderowanie (nieprzezroczystych) ze wspólnego VBO
|
||||
void RenderVBO(); // renderowanie nieprzezroczystych z własnego VBO
|
||||
void RenderAlphaVBO(); // renderowanie przezroczystych z (własnego) VBO
|
||||
|
||||
};
|
||||
|
||||
@@ -222,8 +214,7 @@ class TSubRect : public Resource, public CMesh
|
||||
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
|
||||
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
|
||||
TTraction * FindTraction(vector3 *Point, int &iConnection, TTraction *Exclude);
|
||||
bool StartVBO(); // ustwienie VBO sektora dla (nRenderRect), (nRenderRectAlpha) i
|
||||
// (nRenderWires)
|
||||
bool StartVBO(); // ustwienie VBO sektora dla (nRenderRect), (nRenderRectAlpha) i (nRenderWires)
|
||||
bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
|
||||
void RaAnimate(); // przeliczenie animacji torów
|
||||
void RenderDL(); // renderowanie nieprzezroczystych w Display Lists
|
||||
@@ -299,8 +290,6 @@ class TGround
|
||||
TGroundNode *nRootOfType[TP_LAST]; // tablica grupująca obiekty, przyspiesza szukanie
|
||||
// TGroundNode *nLastOfType[TP_LAST]; //ostatnia
|
||||
TSubRect srGlobal; // zawiera obiekty globalne (na razie wyzwalacze czasowe)
|
||||
int hh = 0,
|
||||
mm = 0; // ustawienia czasu
|
||||
// int tracks,tracksfar; //liczniki torów
|
||||
typedef std::unordered_map<std::string, TEvent *> event_map;
|
||||
event_map m_eventmap;
|
||||
@@ -313,9 +302,6 @@ class TGround
|
||||
public:
|
||||
bool bDynamicRemove = false; // czy uruchomić procedurę usuwania pojazdów
|
||||
TDynamicObject *LastDyn = nullptr; // ABu: paskudnie, ale na bardzo szybko moze jakos przejdzie...
|
||||
// TTrain *pTrain;
|
||||
// double fVDozwolona;
|
||||
// bool bTrabil;
|
||||
|
||||
TGround();
|
||||
~TGround();
|
||||
@@ -329,7 +315,6 @@ class TGround
|
||||
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
|
||||
TTraction * FindTraction(vector3 *Point, int &iConnection, TGroundNode *Exclude);
|
||||
TTraction * TractionNearestFind(vector3 &p, int dir, TGroundNode *n);
|
||||
// TGroundNode* CreateGroundNode();
|
||||
TGroundNode * AddGroundNode(cParser *parser);
|
||||
bool AddGroundNode(double x, double z, TGroundNode *Node)
|
||||
{
|
||||
@@ -342,39 +327,12 @@ class TGround
|
||||
else
|
||||
return false;
|
||||
};
|
||||
// bool Include(TQueryParserComp *Parser);
|
||||
// TGroundNode* GetVisible(AnsiString asName);
|
||||
TGroundNode * GetNode(std::string asName);
|
||||
bool AddDynamic(TGroundNode *Node);
|
||||
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);
|
||||
bool RenderAlphaVBO(vector3 pPosition);
|
||||
bool CheckQuery();
|
||||
// GetRect(double x, double z) { return
|
||||
// &(Rects[int(x/fSubRectSize+fHalfNumRects)][int(z/fSubRectSize+fHalfNumRects)]); };
|
||||
/*
|
||||
int GetRowFromZ(double z) { return (z/fRectSize+fHalfNumRects); };
|
||||
int GetColFromX(double x) { return (x/fRectSize+fHalfNumRects); };
|
||||
int GetSubRowFromZ(double z) { return (z/fSubRectSize+fHalfNumSubRects); };
|
||||
int GetSubColFromX(double x) { return (x/fSubRectSize+fHalfNumSubRects); };
|
||||
*/
|
||||
/*
|
||||
inline TGroundNode* FindGroundNode(const AnsiString &asNameToFind )
|
||||
{
|
||||
if (RootNode)
|
||||
return (RootNode->Find( asNameToFind ));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
TGroundNode * DynamicFindAny(std::string asNameToFind);
|
||||
TGroundNode * DynamicFind(std::string asNameToFind);
|
||||
void DynamicList(bool all = false);
|
||||
@@ -406,7 +364,6 @@ class TGround
|
||||
void TrackJoin(TGroundNode *Current);
|
||||
|
||||
private:
|
||||
void OpenGLUpdate(HDC hDC);
|
||||
void RaTriangleDivider(TGroundNode *node);
|
||||
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
bool PROBLEND;
|
||||
@@ -419,7 +376,6 @@ class TGround
|
||||
void WyslijNamiary(TGroundNode *t);
|
||||
void WyslijParam(int nr, int fl);
|
||||
void WyslijUszkodzenia(const std::string &t, char fl);
|
||||
void WyslijPojazdy(int nr); // -> skladanie wielu pojazdow
|
||||
void WyslijObsadzone(); // -> skladanie wielu pojazdow
|
||||
void RadioStop(vector3 pPosition);
|
||||
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0,
|
||||
|
||||
2
Logs.cpp
2
Logs.cpp
@@ -112,7 +112,7 @@ void ErrorLog(const char *str)
|
||||
"logs/errors (" + filename_scenery() + ") " + filename_date() + ".txt" :
|
||||
"errors.txt" );
|
||||
errors.open( filename, std::ios::trunc );
|
||||
errors << "EU07.EXE " + Global::asRelease << "\n";
|
||||
errors << "EU07.EXE " + Global::asVersion << "\n";
|
||||
}
|
||||
if (str)
|
||||
errors << str;
|
||||
|
||||
@@ -139,6 +139,7 @@ static int const ctrain_passenger = 16; //mostek przejściowy
|
||||
static int const ctrain_scndpneumatic = 32; //przewody 8 atm (żółte; zasilanie powietrzem)
|
||||
static int const ctrain_heating = 64; //przewody ogrzewania WN
|
||||
static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna
|
||||
// possible coupling types; can be combined
|
||||
enum coupling {
|
||||
faux = 0x0,
|
||||
coupler = 0x1,
|
||||
@@ -150,11 +151,16 @@ enum coupling {
|
||||
heating = 0x40,
|
||||
permanent = 0x80
|
||||
};
|
||||
/*! przesylanie komend sterujacych*/
|
||||
enum command_range {
|
||||
// possible effect ranges for control commands; exclusive
|
||||
enum range {
|
||||
local,
|
||||
unit,
|
||||
consist
|
||||
};
|
||||
// start method for devices; exclusive
|
||||
enum start {
|
||||
manual,
|
||||
automatic
|
||||
};
|
||||
/*typ hamulca elektrodynamicznego*/
|
||||
static int const dbrake_none = 0;
|
||||
@@ -842,9 +848,14 @@ public:
|
||||
bool PantCompFlag = false; /*!o czy wlaczona sprezarka pantografow*/
|
||||
bool CompressorAllow = false; /*! zezwolenie na uruchomienie sprezarki NBMX*/
|
||||
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
|
||||
bool ConverterFlag = false ; /*! czy wlaczona przetwornica NBMX*/
|
||||
// TODO converter parameters, for when we start cleaning up mover parameters
|
||||
start ConverterStart{ manual }; // whether converter is started manually, or by other means
|
||||
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
|
||||
double ConverterStartDelayTimer{ 0.0 }; // helper, for tracking whether converter start delay passed
|
||||
bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/
|
||||
int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/
|
||||
bool ConverterFlag = false; /*! czy wlaczona przetwornica NBMX*/
|
||||
|
||||
int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/
|
||||
double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/
|
||||
double BrakeCtrlPos2 = 0.0; /*nastawa hamulca zespolonego - kapturek dla FV4a*/
|
||||
int LocalBrakePos = 0; /*nastawa hamulca indywidualnego*/
|
||||
@@ -1045,7 +1056,7 @@ public:
|
||||
|
||||
bool AddPulseForce(int Multipler);/*dla drezyny*/
|
||||
|
||||
bool Sandbox( bool const State, int const Notify = command_range::consist );/*wlacza/wylacza sypanie piasku*/
|
||||
bool Sandbox( bool const State, int const Notify = range::consist );/*wlacza/wylacza sypanie piasku*/
|
||||
|
||||
/*! zbijanie czuwaka/SHP*/
|
||||
void SSReset(void);
|
||||
@@ -1101,12 +1112,12 @@ public:
|
||||
|
||||
/*--funkcje dla lokomotyw*/
|
||||
bool DirectionBackward(void);/*! kierunek ruchu*/
|
||||
bool MainSwitch( bool const State, int const Notify = command_range::consist );/*! wylacznik glowny*/
|
||||
bool ConverterSwitch( bool State, int const Notify = command_range::consist );/*! wl/wyl przetwornicy*/
|
||||
bool CompressorSwitch( bool State, int const Notify = command_range::consist );/*! wl/wyl sprezarki*/
|
||||
bool MainSwitch( bool const State, int const Notify = range::consist );/*! wylacznik glowny*/
|
||||
bool ConverterSwitch( bool State, int const Notify = range::consist );/*! wl/wyl przetwornicy*/
|
||||
bool CompressorSwitch( bool State, int const Notify = range::consist );/*! wl/wyl sprezarki*/
|
||||
|
||||
/*-funkcje typowe dla lokomotywy elektrycznej*/
|
||||
void ConverterCheck(); // przetwornica
|
||||
void ConverterCheck( double const Timestep ); // przetwornica
|
||||
bool FuseOn(void); //bezpiecznik nadamiary
|
||||
bool FuseFlagCheck(void); // sprawdzanie flagi nadmiarowego
|
||||
void FuseOff(void); // wylaczenie nadmiarowego
|
||||
@@ -1129,8 +1140,8 @@ public:
|
||||
bool AutoRelayCheck(void);//symulacja automatycznego rozruchu
|
||||
|
||||
bool ResistorsFlagCheck(void); //sprawdzenie kontrolki oporow rozruchowych NBMX
|
||||
bool PantFront( bool const State, int const Notify = command_range::consist ); //obsluga pantografou przedniego
|
||||
bool PantRear( bool const State, int const Notify = command_range::consist ); //obsluga pantografu tylnego
|
||||
bool PantFront( bool const State, int const Notify = range::consist ); //obsluga pantografou przedniego
|
||||
bool PantRear( bool const State, int const Notify = range::consist ); //obsluga pantografu tylnego
|
||||
|
||||
/*-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna*/
|
||||
bool dizel_EngageSwitch(double state);
|
||||
|
||||
@@ -773,7 +773,7 @@ void TMoverParameters::UpdatePantVolume(double dt)
|
||||
// wywalenie szybkiego z powodu niskiego ciśnienia
|
||||
if( GetTrainsetVoltage() < 0.5 * EnginePowerSource.MaxVoltage ) {
|
||||
// to jest trochę proteza; zasilanie członu może być przez sprzęg WN
|
||||
if( MainSwitch( false, ( TrainType == dt_EZT ? command_range::unit : command_range::local ) ) ) {
|
||||
if( MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ) ) {
|
||||
EventFlag = true;
|
||||
}
|
||||
}
|
||||
@@ -1366,7 +1366,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
|
||||
Compressor = 0;
|
||||
CompressorFlag = false;
|
||||
};
|
||||
ConverterCheck();
|
||||
ConverterCheck(dt);
|
||||
if (CompressorSpeed > 0.0) // sprężarka musi mieć jakąś niezerową wydajność
|
||||
CompressorCheck(dt); //żeby rozważać jej załączenie i pracę
|
||||
UpdateBrakePressure(dt);
|
||||
@@ -1522,7 +1522,7 @@ double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape
|
||||
Compressor = 0;
|
||||
CompressorFlag = false;
|
||||
};
|
||||
ConverterCheck();
|
||||
ConverterCheck(dt);
|
||||
if (CompressorSpeed > 0.0) // sprężarka musi mieć jakąś niezerową wydajność
|
||||
CompressorCheck(dt); //żeby rozważać jej załączenie i pracę
|
||||
UpdateBrakePressure(dt);
|
||||
@@ -1561,15 +1561,23 @@ double TMoverParameters::ShowEngineRotation(int VehN)
|
||||
return 0.0;
|
||||
};
|
||||
|
||||
void TMoverParameters::ConverterCheck()
|
||||
{ // sprawdzanie przetwornicy
|
||||
// sprawdzanie przetwornicy
|
||||
void TMoverParameters::ConverterCheck( double const Timestep ) {
|
||||
// TODO: move other converter checks here, to have it all in one place for potential device object
|
||||
if( ( ConverterAllow )
|
||||
&& ( false == PantPressLockActive )
|
||||
&& ( Mains ) ) {
|
||||
ConverterFlag = true;
|
||||
// delay timer can be optionally configured, and is set anew whenever converter goes off
|
||||
if( ConverterStartDelayTimer <= 0.0 ) {
|
||||
ConverterFlag = true;
|
||||
}
|
||||
else {
|
||||
ConverterStartDelayTimer -= Timestep;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ConverterFlag = false;
|
||||
ConverterStartDelayTimer = static_cast<double>( ConverterStartDelay );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2087,10 +2095,10 @@ bool TMoverParameters::Sandbox( bool const State, int const Notify )
|
||||
}
|
||||
}
|
||||
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// if requested pass the command on
|
||||
auto const couplingtype =
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll );
|
||||
|
||||
@@ -2348,11 +2356,11 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify )
|
||||
{
|
||||
if( Mains ) {
|
||||
// jeśli był załączony
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"MainSwitch", int( State ), CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
@@ -2360,11 +2368,11 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify )
|
||||
Mains = State;
|
||||
if( Mains ) {
|
||||
// jeśli został załączony
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"MainSwitch", int( State ), CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
@@ -2399,19 +2407,19 @@ bool TMoverParameters::ConverterSwitch( bool State, int const Notify )
|
||||
CompressorAllow = ConverterAllow;
|
||||
}
|
||||
if( ConverterAllow == true ) {
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
SendCtrlToNext(
|
||||
"ConverterSwitch", 1, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
SendCtrlToNext(
|
||||
"ConverterSwitch", 0, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
@@ -2436,19 +2444,19 @@ bool TMoverParameters::CompressorSwitch( bool State, int const Notify )
|
||||
CS = true;
|
||||
}
|
||||
if( CompressorAllow == true ) {
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
SendCtrlToNext(
|
||||
"CompressorSwitch", 1, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
SendCtrlToNext(
|
||||
"CompressorSwitch", 0, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
@@ -4165,7 +4173,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
if ( (std::max(GetTrainsetVoltage(), std::abs(Voltage)) < EnginePowerSource.CollectorParameters.MinV) ||
|
||||
(std::max(GetTrainsetVoltage(), std::abs(Voltage)) * EnginePowerSource.CollectorParameters.OVP >
|
||||
EnginePowerSource.CollectorParameters.MaxV))
|
||||
if( MainSwitch( false, ( TrainType == dt_EZT ? command_range::unit : command_range::local ) ) ) // TODO: check whether we need to send this EMU-wide
|
||||
if( MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ) ) // TODO: check whether we need to send this EMU-wide
|
||||
EventFlag = true; // wywalanie szybkiego z powodu niewłaściwego napięcia
|
||||
|
||||
if (((DynamicBrakeType == dbrake_automatic) || (DynamicBrakeType == dbrake_switch)) &&
|
||||
@@ -4464,7 +4472,7 @@ double TMoverParameters::TractionForce(double dt)
|
||||
// nie wchodzić w funkcję bez potrzeby
|
||||
if( ( std::max( std::abs( Voltage ), GetTrainsetVoltage() ) < EnginePowerSource.CollectorParameters.MinV )
|
||||
|| ( std::max( std::abs( Voltage ), GetTrainsetVoltage() ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) {
|
||||
MainSwitch( false, ( TrainType == dt_EZT ? command_range::unit : command_range::local ) ); // TODO: check whether we need to send this EMU-wide
|
||||
MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ); // TODO: check whether we need to send this EMU-wide
|
||||
}
|
||||
}
|
||||
tmpV = abs(nrot) * (PI * WheelDiameter) * 3.6; //*DirAbsolute*eimc[eimc_s_p]; - do przemyslenia dzialanie pp
|
||||
@@ -4538,21 +4546,21 @@ double TMoverParameters::TractionForce(double dt)
|
||||
{
|
||||
PosRatio = 0;
|
||||
tmp = 4;
|
||||
Sandbox( true, command_range::local );
|
||||
Sandbox( true, range::local );
|
||||
} // przeciwposlizg
|
||||
if ((abs((PosRatio + 9.80 * dizel_fill) * dmoment * 100) >
|
||||
0.95 * Adhesive(RunningTrack.friction) * TotalMassxg))
|
||||
{
|
||||
PosRatio = 0;
|
||||
tmp = 9;
|
||||
Sandbox( true, command_range::local );
|
||||
Sandbox( true, range::local );
|
||||
} // przeciwposlizg
|
||||
if ((SlippingWheels))
|
||||
{
|
||||
// PosRatio = -PosRatio * 0; // serio -0 ???
|
||||
PosRatio = 0;
|
||||
tmp = 9;
|
||||
Sandbox( true, command_range::local );
|
||||
Sandbox( true, range::local );
|
||||
} // przeciwposlizg
|
||||
|
||||
dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.1), -0.1) * 2 *
|
||||
@@ -5190,22 +5198,22 @@ bool TMoverParameters::PantFront( bool const State, int const Notify )
|
||||
PantFrontUp = State;
|
||||
if( State == true ) {
|
||||
PantFrontStart = 0;
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"PantFront", 1, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
PantFrontStart = 1;
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"PantFront", 0, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
@@ -5243,22 +5251,22 @@ bool TMoverParameters::PantRear( bool const State, int const Notify )
|
||||
PantRearUp = State;
|
||||
if( State == true ) {
|
||||
PantRearStart = 0;
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"PantRear", 1, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
PantRearStart = 1;
|
||||
if( Notify != command_range::local ) {
|
||||
if( Notify != range::local ) {
|
||||
// wysłanie wyłączenia do pozostałych?
|
||||
SendCtrlToNext(
|
||||
"PantRear", 0, CabNo,
|
||||
( Notify == command_range::unit ?
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
}
|
||||
@@ -7048,6 +7056,20 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
0;
|
||||
|
||||
extract_value( StopBrakeDecc, "SBD", line, "" );
|
||||
|
||||
// converter
|
||||
{
|
||||
std::map<std::string, start> starts{
|
||||
{ "Manual", start::manual },
|
||||
{ "Automatic", start::automatic }
|
||||
};
|
||||
auto lookup = starts.find( extract_value( "ConverterStart", line ) );
|
||||
ConverterStart =
|
||||
lookup != starts.end() ?
|
||||
lookup->second :
|
||||
start::manual;
|
||||
}
|
||||
extract_value( ConverterStartDelay, "ConverterStartDelay", line, "" );
|
||||
}
|
||||
|
||||
void TMoverParameters::LoadFIZ_Light( std::string const &line ) {
|
||||
@@ -8148,7 +8170,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
}
|
||||
else if (Command == "Sandbox")
|
||||
{
|
||||
OK = Sandbox( CValue1 == 1, command_range::local );
|
||||
OK = Sandbox( CValue1 == 1, range::local );
|
||||
}
|
||||
else if (Command == "CabSignal") /*SHP,Indusi*/
|
||||
{ // Ra: to powinno działać tylko w członie obsadzonym
|
||||
|
||||
887
Segment.cpp
887
Segment.cpp
@@ -19,12 +19,6 @@ 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);
|
||||
@@ -122,15 +116,14 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
|
||||
// MessageBox(0,"Length<=0","TSegment::Init",MB_OK);
|
||||
return false; // zerowe nie mogą być
|
||||
}
|
||||
fStoop = atan2((Point2.y - Point1.y),
|
||||
fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
||||
fStoop = std::atan2((Point2.y - Point1.y), fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
|
||||
SafeDeleteArray(fTsBuffer);
|
||||
|
||||
if( ( bCurve ) && ( fStep > 0 ) ) {
|
||||
if( fStep > 0 ) { // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
|
||||
double s = 0;
|
||||
int i = 0;
|
||||
iSegCount = ceil( fLength / fStep ); // potrzebne do VBO
|
||||
iSegCount = static_cast<int>( std::ceil( fLength / fStep )); // potrzebne do VBO
|
||||
// fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
|
||||
fTsBuffer = new double[ iSegCount + 1 ];
|
||||
fTsBuffer[ 0 ] = 0; /* TODO : fix fTsBuffer */
|
||||
@@ -324,408 +317,213 @@ vector3 TSegment::FastGetPoint(double t)
|
||||
return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2));
|
||||
}
|
||||
|
||||
void TSegment::RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength,
|
||||
int iSkip, int iQualityFactor, vector3 **p, bool bRender)
|
||||
void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, bool Onlypositions, vector3 **p, bool bRender)
|
||||
{ // generowanie trójkątów dla odcinka trajektorii ruchu
|
||||
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
|
||||
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
|
||||
// podany jest przekrój końcowy
|
||||
// podsypka toru jest robiona za pomocą 6 punktów, szyna 12, drogi i rzeki na 3+2+3
|
||||
if (iQualityFactor < 1)
|
||||
iQualityFactor = 1; // co który segment ma być uwzględniony
|
||||
if( !fTsBuffer )
|
||||
return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
||||
|
||||
vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
|
||||
double s, step, fOffset, tv1, tv2, t;
|
||||
int i, j;
|
||||
bool trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
|
||||
iNumShapePoints = abs(iNumShapePoints);
|
||||
if (bCurve)
|
||||
{
|
||||
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
|
||||
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
|
||||
step = fStep * iQualityFactor;
|
||||
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
|
||||
i = iSkip; // domyślnie 0
|
||||
if (!fTsBuffer)
|
||||
return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
||||
if (i > iSegCount)
|
||||
return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
||||
t = fTsBuffer[i]; // tabela watości t dla segmentów
|
||||
fOffset = 0.1 / fLength; // pierwsze 10cm
|
||||
pos1 = FastGetPoint(t); // wektor początku segmentu
|
||||
dir = FastGetDirection(t, fOffset); // wektor kierunku
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //wektor poprzeczny
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
m2 = s / fLength;
|
||||
jmm2 = 1.0 - m2;
|
||||
while (s < fLength)
|
||||
{
|
||||
// step=SquareMagnitude(Global::GetCameraPosition()+pos);
|
||||
i += iQualityFactor; // kolejny punkt łamanej
|
||||
s += step; // końcowa pozycja segmentu [m]
|
||||
m1 = m2;
|
||||
jmm1 = jmm2; // stara pozycja
|
||||
m2 = s / fLength;
|
||||
jmm2 = 1.0 - m2; // nowa pozycja
|
||||
if (s > fLength - 0.5) // Ra: -0.5 żeby nie robiło cieniasa na końcu
|
||||
{ // gdy przekroczyliśmy koniec - stąd dziury w torach...
|
||||
step -= (s - fLength); // jeszcze do wyliczenia mapowania potrzebny
|
||||
s = fLength;
|
||||
i = iSegCount; // 20/5 ma dawać 4
|
||||
m2 = 1.0;
|
||||
jmm2 = 0.0;
|
||||
}
|
||||
while (tv1 < 0.0)
|
||||
tv1 += 1.0; // przestawienie mapowania
|
||||
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
|
||||
t = fTsBuffer[i]; // szybsze od GetTFromS(s);
|
||||
pos2 = FastGetPoint(t);
|
||||
dir = FastGetDirection(t, fOffset); // nowy wektor kierunku
|
||||
// parallel2=CrossProduct(dir,vector3(0,1,0)); //wektor poprzeczny
|
||||
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
if (trapez)
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
|
||||
parallel1;
|
||||
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
|
||||
pt = parallel1 *
|
||||
(jmm1 * ShapePoints[j].x + m1 * ShapePoints[j + iNumShapePoints].x) +
|
||||
pos1;
|
||||
pt.y += jmm1 * ShapePoints[j].y + m1 * ShapePoints[j + iNumShapePoints].y;
|
||||
if (bRender)
|
||||
{ // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale
|
||||
// potrzebować punktów
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(
|
||||
jmm1 * ShapePoints[j].z + m1 * ShapePoints[j + iNumShapePoints].z, tv1);
|
||||
glVertex3f(pt.x, pt.y, pt.z); // pt nie mamy gdzie zapamiętać?
|
||||
}
|
||||
// BUG: things blow up badly in the following part in 64bit version on baltyk.scn
|
||||
// TODO: sort this mess out when the time comes to reorganize spline generation
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if (*p)
|
||||
if (!j) // to dla pierwszego punktu
|
||||
{
|
||||
*(*p) = pt;
|
||||
(*p)++;
|
||||
} // zapamiętanie brzegu jezdni
|
||||
// dla trapezu drugi koniec ma inne współrzędne
|
||||
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
|
||||
parallel2;
|
||||
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
|
||||
pt = parallel2 *
|
||||
(jmm2 * ShapePoints[j].x + m2 * ShapePoints[j + iNumShapePoints].x) +
|
||||
pos2;
|
||||
pt.y += jmm2 * ShapePoints[j].y + m2 * ShapePoints[j + iNumShapePoints].y;
|
||||
if (bRender)
|
||||
{ // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale
|
||||
// potrzebować punktów
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(
|
||||
jmm2 * ShapePoints[j].z + m2 * ShapePoints[j + iNumShapePoints].z, tv2);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
}
|
||||
if (p) // jeśli jest wskaźnik do tablicy
|
||||
if (*p)
|
||||
if (!j) // to dla pierwszego punktu
|
||||
if (i == iSegCount)
|
||||
{
|
||||
*(*p) = pt;
|
||||
(*p)++;
|
||||
} // zapamiętanie brzegu jezdni
|
||||
}
|
||||
else
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{ //łuk z jednym profilem
|
||||
norm = ShapePoints[j].n.x * parallel1;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel1 * ShapePoints[j].x + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(ShapePoints[j].z, tv1);
|
||||
glVertex3f(pt.x, pt.y, pt.z); // punkt na początku odcinka
|
||||
norm = ShapePoints[j].n.x * parallel2;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel2 * ShapePoints[j].x + pos2;
|
||||
pt.y += ShapePoints[j].y;
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(ShapePoints[j].z, tv2);
|
||||
glVertex3f(pt.x, pt.y, pt.z); // punkt na końcu odcinka
|
||||
}
|
||||
glEnd();
|
||||
pos1 = pos2;
|
||||
parallel1 = parallel2;
|
||||
tv1 = tv2;
|
||||
double s, step, fOffset, tv1, tv2, t, fEnd;
|
||||
bool const trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
|
||||
iNumShapePoints = std::abs( iNumShapePoints );
|
||||
fTextureLength *= Texturescale;
|
||||
|
||||
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
|
||||
step = fStep;
|
||||
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
|
||||
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
|
||||
int i = iSkip; // domyślnie 0
|
||||
t = fTsBuffer[ i ]; // tabela wattości t dla segmentów
|
||||
// BUG: length of spline can be 0, we should skip geometry generation for such cases
|
||||
fOffset = 0.1 / fLength; // pierwsze 10cm
|
||||
pos1 = FastGetPoint( t ); // wektor początku segmentu
|
||||
dir = FastGetDirection( t, fOffset ); // wektor kierunku
|
||||
parallel1 = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
|
||||
if( iEnd == 0 )
|
||||
iEnd = iSegCount;
|
||||
fEnd = fLength * double( iEnd ) / double( iSegCount );
|
||||
m2 = s / fEnd;
|
||||
jmm2 = 1.0 - m2;
|
||||
while( i < iEnd ) {
|
||||
|
||||
++i; // kolejny punkt łamanej
|
||||
s += step; // końcowa pozycja segmentu [m]
|
||||
m1 = m2;
|
||||
jmm1 = jmm2; // stara pozycja
|
||||
m2 = s / fEnd;
|
||||
jmm2 = 1.0 - m2; // nowa pozycja
|
||||
if( i == iEnd ) { // gdy przekroczyliśmy koniec - stąd dziury w torach...
|
||||
step -= ( s - fEnd ); // jeszcze do wyliczenia mapowania potrzebny
|
||||
s = fEnd;
|
||||
m2 = 1.0;
|
||||
jmm2 = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef EU07_USE_OLD_LIGHTING_MODEL
|
||||
{ // gdy prosty, nie modyfikujemy wektora kierunkowego i poprzecznego
|
||||
pos1 = FastGetPoint((fStep * iSkip) / fLength);
|
||||
pos2 = FastGetPoint_1();
|
||||
dir = GetDirection();
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0)));
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
if (trapez)
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
norm = ShapePoints[j].n.x * parallel1;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel1 * ShapePoints[j].x + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(ShapePoints[j].z, 0);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
// dla trapezu drugi koniec ma inne współrzędne względne
|
||||
norm = ShapePoints[j + iNumShapePoints].n.x * parallel1;
|
||||
norm.y += ShapePoints[j + iNumShapePoints].n.y;
|
||||
pt = parallel1 * ShapePoints[j + iNumShapePoints].x + pos2; // odsunięcie
|
||||
pt.y += ShapePoints[j + iNumShapePoints].y; // wysokość
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(ShapePoints[j + iNumShapePoints].z, fLength / fTextureLength);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
|
||||
if( false == Onlypositions ) {
|
||||
while( tv1 < 0.0 ) {
|
||||
tv1 += 1.0;
|
||||
}
|
||||
else
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
norm = ShapePoints[j].n.x * parallel1;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel1 * ShapePoints[j].x + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(ShapePoints[j].z, 0);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
pt = parallel1 * ShapePoints[j].x + pos2;
|
||||
pt.y += ShapePoints[j].y;
|
||||
glNormal3f(norm.x, norm.y, norm.z);
|
||||
glTexCoord2f(ShapePoints[j].z, fLength / fTextureLength);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
|
||||
}
|
||||
|
||||
t = fTsBuffer[ i ]; // szybsze od GetTFromS(s);
|
||||
pos2 = FastGetPoint( t );
|
||||
dir = FastGetDirection( t, fOffset ); // nowy wektor kierunku
|
||||
parallel2 = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
|
||||
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
::glBegin( GL_TRIANGLE_STRIP );
|
||||
}
|
||||
|
||||
if( trapez ) {
|
||||
for( int j = 0; j < iNumShapePoints; ++j ) {
|
||||
pt = parallel1 * ( jmm1 * ( ShapePoints[ j ].x - fOffsetX ) + m1 * ShapePoints[ j + iNumShapePoints ].x ) + pos1;
|
||||
pt.y += jmm1 * ShapePoints[ j ].y + m1 * ShapePoints[ j + iNumShapePoints ].y;
|
||||
if( false == Onlypositions ) {
|
||||
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel1;
|
||||
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
|
||||
}
|
||||
if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
if( false == Onlypositions ) {
|
||||
::glNormal3f( norm.x, norm.y, norm.z );
|
||||
::glTexCoord2f( (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv1 );
|
||||
}
|
||||
::glVertex3f( pt.x, pt.y, pt.z ); // pt nie mamy gdzie zapamiętać?
|
||||
}
|
||||
else {
|
||||
Output->x = pt.x;
|
||||
Output->y = pt.y;
|
||||
Output->z = pt.z;
|
||||
if( false == Onlypositions ) {
|
||||
Output->nx = norm.x;
|
||||
Output->ny = norm.y;
|
||||
Output->nz = norm.z;
|
||||
Output->u = (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
|
||||
Output->v = tv1;
|
||||
}
|
||||
++Output;
|
||||
}
|
||||
}
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if( *p )
|
||||
if( !j ) // to dla pierwszego punktu
|
||||
{
|
||||
*( *p ) = pt;
|
||||
( *p )++;
|
||||
} // zapamiętanie brzegu jezdni
|
||||
// dla trapezu drugi koniec ma inne współrzędne
|
||||
pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].x - fOffsetX ) + m2 * ShapePoints[ j + iNumShapePoints ].x ) + pos2;
|
||||
pt.y += jmm2 * ShapePoints[ j ].y + m2 * ShapePoints[ j + iNumShapePoints ].y;
|
||||
if( false == Onlypositions ) {
|
||||
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel2;
|
||||
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
|
||||
}
|
||||
if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
if( false == Onlypositions ) {
|
||||
::glNormal3f( norm.x, norm.y, norm.z );
|
||||
::glTexCoord2f( (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv2 );
|
||||
}
|
||||
::glVertex3f( pt.x, pt.y, pt.z );
|
||||
}
|
||||
else {
|
||||
Output->x = pt.x;
|
||||
Output->y = pt.y;
|
||||
Output->z = pt.z;
|
||||
if( false == Onlypositions ) {
|
||||
Output->nx = norm.x;
|
||||
Output->ny = norm.y;
|
||||
Output->nz = norm.z;
|
||||
Output->u = (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
|
||||
Output->v = tv2;
|
||||
}
|
||||
++Output;
|
||||
}
|
||||
}
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if( *p )
|
||||
if( !j ) // to dla pierwszego punktu
|
||||
if( i == iSegCount ) {
|
||||
*( *p ) = pt;
|
||||
( *p )++;
|
||||
} // zapamiętanie brzegu jezdni
|
||||
}
|
||||
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,
|
||||
int iNumShapePoints, double fTextureLength, int iSkip,
|
||||
double fOffsetX)
|
||||
{ // tworzenie siatki trójkątów dla iglicy
|
||||
vector3 pos1, pos2, dir, parallel1, parallel2, pt;
|
||||
double a1, a2, s, step, offset, tv1, tv2, t, t2step, oldt2;
|
||||
int i, j;
|
||||
if (bCurve)
|
||||
{ // dla toru odchylonego
|
||||
// t2= 0;
|
||||
t2step = 1 / double(iSkip); // przesunięcie tekstury?
|
||||
oldt2 = 1;
|
||||
tv1 = 1.0;
|
||||
step = fStep; // długść segmentu
|
||||
s = 0;
|
||||
i = 0;
|
||||
t = fTsBuffer[i]; // wartość t krzywej Beziera dla początku
|
||||
a1 = 0;
|
||||
// step= fStep/fLength;
|
||||
offset = 0.1 / fLength; // około 10cm w sensie parametru t
|
||||
pos1 = FastGetPoint(t); // współrzędne dla parmatru t
|
||||
// dir= GetDirection1();
|
||||
dir = FastGetDirection(t, offset); // wektor wzdłużny
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //poprzeczny?
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
|
||||
while (s < fLength && i < iSkip)
|
||||
{
|
||||
// step= SquareMagnitude(Global::GetCameraPosition()+pos);
|
||||
// t2= oldt2+t2step;
|
||||
i++;
|
||||
s += step;
|
||||
|
||||
if (s > fLength)
|
||||
{
|
||||
step -= (s - fLength);
|
||||
s = fLength;
|
||||
}
|
||||
|
||||
while (tv1 < 0.0)
|
||||
tv1 += 1.0;
|
||||
tv2 = tv1 - step / fTextureLength;
|
||||
|
||||
t = fTsBuffer[i];
|
||||
pos2 = FastGetPoint(t);
|
||||
dir = FastGetDirection(t, offset);
|
||||
// parallel2=Normalize(CrossProduct(dir,vector3(0,1,0)));
|
||||
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
|
||||
a2 = double(i) / (iSkip);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{ // po dwa punkty trapezu
|
||||
pt = parallel1 *
|
||||
(ShapePoints1[j].x * a1 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a1)) +
|
||||
pos1;
|
||||
pt.y += ShapePoints1[j].y * a1 + ShapePoints2[j].y * (1.0 - a1);
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glTexCoord2f(ShapePoints1[j].z * a1 + ShapePoints2[j].z * (1.0 - a1), tv1);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
|
||||
pt = parallel2 *
|
||||
(ShapePoints1[j].x * a2 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a2)) +
|
||||
pos2;
|
||||
pt.y += ShapePoints1[j].y * a2 + ShapePoints2[j].y * (1.0 - a2);
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glTexCoord2f(ShapePoints1[j].z * a2 + ShapePoints2[j].z * (1.0 - a2), tv2);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
for( int j = 0; j < iNumShapePoints; ++j ) {
|
||||
//łuk z jednym profilem
|
||||
pt = parallel1 * ( ShapePoints[ j ].x - fOffsetX ) + pos1;
|
||||
pt.y += ShapePoints[ j ].y;
|
||||
if( false == Onlypositions ) {
|
||||
norm = ShapePoints[ j ].n.x * parallel1;
|
||||
norm.y += ShapePoints[ j ].n.y;
|
||||
}
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
if( false == Onlypositions ) {
|
||||
::glNormal3f( norm.x, norm.y, norm.z );
|
||||
::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv1 );
|
||||
}
|
||||
::glVertex3f( pt.x, pt.y, pt.z ); // punkt na początku odcinka
|
||||
}
|
||||
else {
|
||||
Output->x = pt.x;
|
||||
Output->y = pt.y;
|
||||
Output->z = pt.z;
|
||||
if( false == Onlypositions ) {
|
||||
Output->nx = norm.x;
|
||||
Output->ny = norm.y;
|
||||
Output->nz = norm.z;
|
||||
Output->u = ShapePoints[ j ].z / Texturescale;
|
||||
Output->v = tv1;
|
||||
}
|
||||
++Output;
|
||||
}
|
||||
pt = parallel2 * ShapePoints[ j ].x + pos2;
|
||||
pt.y += ShapePoints[ j ].y;
|
||||
if( false == Onlypositions ) {
|
||||
norm = ShapePoints[ j ].n.x * parallel2;
|
||||
norm.y += ShapePoints[ j ].n.y;
|
||||
}
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
if( false == Onlypositions ) {
|
||||
::glNormal3f( norm.x, norm.y, norm.z );
|
||||
::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv2 );
|
||||
}
|
||||
::glVertex3f( pt.x, pt.y, pt.z ); // punkt na końcu odcinka
|
||||
}
|
||||
else {
|
||||
Output->x = pt.x;
|
||||
Output->y = pt.y;
|
||||
Output->z = pt.z;
|
||||
if( false == Onlypositions ) {
|
||||
Output->nx = norm.x;
|
||||
Output->ny = norm.y;
|
||||
Output->nz = norm.z;
|
||||
Output->u = ShapePoints[ j ].z / Texturescale;
|
||||
Output->v = tv2;
|
||||
}
|
||||
++Output;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
glEnd();
|
||||
pos1 = pos2;
|
||||
parallel1 = parallel2;
|
||||
tv1 = tv2;
|
||||
a1 = a2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // dla toru prostego
|
||||
tv1 = 1.0;
|
||||
s = 0;
|
||||
i = 0;
|
||||
// pos1= FastGetPoint( (5*iSkip)/fLength );
|
||||
pos1 = FastGetPoint_0();
|
||||
dir = GetDirection();
|
||||
// parallel1=CrossProduct(dir,vector3(0,1,0));
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
|
||||
step = 5;
|
||||
a1 = 0;
|
||||
|
||||
while (i < iSkip)
|
||||
{
|
||||
// step= SquareMagnitude(Global::GetCameraPosition()+pos);
|
||||
i++;
|
||||
s += step;
|
||||
|
||||
if (s > fLength)
|
||||
{
|
||||
step -= (s - fLength);
|
||||
s = fLength;
|
||||
}
|
||||
|
||||
while (tv1 < 0.0)
|
||||
tv1 += 1.0;
|
||||
|
||||
tv2 = tv1 - step / fTextureLength;
|
||||
|
||||
t = s / fLength;
|
||||
pos2 = FastGetPoint(t);
|
||||
|
||||
a2 = double(i) / (iSkip);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
pt = parallel1 *
|
||||
(ShapePoints1[j].x * a1 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a1)) +
|
||||
pos1;
|
||||
pt.y += ShapePoints1[j].y * a1 + ShapePoints2[j].y * (1.0 - a1);
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glTexCoord2f((ShapePoints1[j].z), tv1);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
|
||||
pt = parallel1 *
|
||||
(ShapePoints1[j].x * a2 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a2)) +
|
||||
pos2;
|
||||
pt.y += ShapePoints1[j].y * a2 + ShapePoints2[j].y * (1.0 - a2);
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glTexCoord2f(ShapePoints2[j].z, tv2);
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
}
|
||||
glEnd();
|
||||
pos1 = pos2;
|
||||
pos1 = pos2;
|
||||
parallel1 = parallel2;
|
||||
if( false == Onlypositions ) {
|
||||
tv1 = tv2;
|
||||
a1 = a2;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -778,301 +576,4 @@ void TSegment::Render()
|
||||
}
|
||||
}
|
||||
|
||||
void TSegment::RaRenderLoft(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
|
||||
double fTextureLength, int iSkip, int iEnd, double fOffsetX)
|
||||
{ // generowanie trójkątów dla odcinka trajektorii ruchu
|
||||
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
|
||||
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
|
||||
// podany jest przekrój końcowy
|
||||
// podsypka toru jest robiona za pomocą 6 punktów, szyna 12, drogi i rzeki na 3+2+3
|
||||
// na użytek VBO strip dla łuków jest tworzony wzdłuż
|
||||
// dla skróconego odcinka (iEnd<iSegCount), ShapePoints dotyczy
|
||||
// końców skróconych, a nie całości (to pod kątem iglic jest)
|
||||
vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
|
||||
double s, step, fOffset, tv1, tv2, t, fEnd;
|
||||
int i, j;
|
||||
bool trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
|
||||
iNumShapePoints = abs(iNumShapePoints);
|
||||
if (bCurve)
|
||||
{
|
||||
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
|
||||
step = fStep;
|
||||
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
|
||||
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
|
||||
i = iSkip; // domyślnie 0
|
||||
t = fTsBuffer[i]; // tabela wattości t dla segmentów
|
||||
// BUG: length of spline can be 0, we should skip geometry generation for such cases
|
||||
fOffset = 0.1 / fLength; // pierwsze 10cm
|
||||
pos1 = FastGetPoint(t); // wektor początku segmentu
|
||||
dir = FastGetDirection(t, fOffset); // wektor kierunku
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //wektor prostopadły
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
if (iEnd == 0)
|
||||
iEnd = iSegCount;
|
||||
fEnd = fLength * double(iEnd) / double(iSegCount);
|
||||
m2 = s / fEnd;
|
||||
jmm2 = 1.0 - m2;
|
||||
while (i < iEnd)
|
||||
{
|
||||
++i; // kolejny punkt łamanej
|
||||
s += step; // końcowa pozycja segmentu [m]
|
||||
m1 = m2;
|
||||
jmm1 = jmm2; // stara pozycja
|
||||
m2 = s / fEnd;
|
||||
jmm2 = 1.0 - m2; // nowa pozycja
|
||||
if (i == iEnd)
|
||||
{ // gdy przekroczyliśmy koniec - stąd dziury w torach...
|
||||
step -= (s - fEnd); // jeszcze do wyliczenia mapowania potrzebny
|
||||
s = fEnd;
|
||||
// i=iEnd; //20/5 ma dawać 4
|
||||
m2 = 1.0;
|
||||
jmm2 = 0.0;
|
||||
}
|
||||
while (tv1 < 0.0)
|
||||
tv1 += 1.0;
|
||||
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
|
||||
t = fTsBuffer[i]; // szybsze od GetTFromS(s);
|
||||
pos2 = FastGetPoint(t);
|
||||
dir = FastGetDirection(t, fOffset); // nowy wektor kierunku
|
||||
// parallel2=Normalize(CrossProduct(dir,vector3(0,1,0)));
|
||||
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
if (trapez)
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{ // współrzędne początku
|
||||
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
|
||||
parallel1;
|
||||
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
|
||||
pt = parallel1 * (jmm1 * (ShapePoints[j].x - fOffsetX) +
|
||||
m1 * ShapePoints[j + iNumShapePoints].x) +
|
||||
pos1;
|
||||
pt.y += jmm1 * ShapePoints[j].y + m1 * ShapePoints[j + iNumShapePoints].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = jmm1 * ShapePoints[j].z + m1 * ShapePoints[j + iNumShapePoints].z;
|
||||
Vert->v = tv1;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na początku odcinka
|
||||
Vert++;
|
||||
// dla trapezu drugi koniec ma inne współrzędne względne
|
||||
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
|
||||
parallel2;
|
||||
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
|
||||
pt = parallel2 * (jmm2 * (ShapePoints[j].x - fOffsetX) +
|
||||
m2 * ShapePoints[j + iNumShapePoints].x) +
|
||||
pos2;
|
||||
pt.y += jmm2 * ShapePoints[j].y + m2 * ShapePoints[j + iNumShapePoints].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = jmm2 * ShapePoints[j].z + m2 * ShapePoints[j + iNumShapePoints].z;
|
||||
Vert->v = tv2;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na końcu odcinka
|
||||
Vert++;
|
||||
}
|
||||
else
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{ // współrzędne początku
|
||||
norm = ShapePoints[j].n.x * parallel1;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = ShapePoints[j].z;
|
||||
Vert->v = tv1;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na początku odcinka
|
||||
Vert++;
|
||||
norm = ShapePoints[j].n.x * parallel2;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel2 * ShapePoints[j].x + pos2;
|
||||
pt.y += ShapePoints[j].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = ShapePoints[j].z;
|
||||
Vert->v = tv2;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na końcu odcinka
|
||||
Vert++;
|
||||
}
|
||||
pos1 = pos2;
|
||||
parallel1 = parallel2;
|
||||
tv1 = tv2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // gdy prosty
|
||||
pos1 = FastGetPoint((fStep * iSkip) / fLength);
|
||||
pos2 = FastGetPoint_1();
|
||||
dir = GetDirection();
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0)));
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
if (trapez)
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
norm = ShapePoints[j].n.x * parallel1;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = ShapePoints[j].z;
|
||||
Vert->v = 0;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na początku odcinka
|
||||
Vert++;
|
||||
// dla trapezu drugi koniec ma inne współrzędne
|
||||
norm = ShapePoints[j + iNumShapePoints].n.x * parallel1;
|
||||
norm.y += ShapePoints[j + iNumShapePoints].n.y;
|
||||
pt = parallel1 * (ShapePoints[j + iNumShapePoints].x - fOffsetX) +
|
||||
pos2; // odsunięcie
|
||||
pt.y += ShapePoints[j + iNumShapePoints].y; // wysokość
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = ShapePoints[j + iNumShapePoints].z;
|
||||
Vert->v = fLength / fTextureLength;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na końcu odcinka
|
||||
Vert++;
|
||||
}
|
||||
else
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
norm = ShapePoints[j].n.x * parallel1;
|
||||
norm.y += ShapePoints[j].n.y;
|
||||
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = ShapePoints[j].z;
|
||||
Vert->v = 0;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na początku odcinka
|
||||
Vert++;
|
||||
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos2;
|
||||
pt.y += ShapePoints[j].y;
|
||||
Vert->nx = norm.x; // niekoniecznie tak
|
||||
Vert->ny = norm.y;
|
||||
Vert->nz = norm.z;
|
||||
Vert->u = ShapePoints[j].z;
|
||||
Vert->v = fLength / fTextureLength;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na końcu odcinka
|
||||
Vert++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void TSegment::RaAnimate(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
|
||||
double fTextureLength, int iSkip, int iEnd, double fOffsetX)
|
||||
{ // jak wyżej, tylko z pominięciem mapowania i braku trapezowania
|
||||
vector3 pos1, pos2, dir, parallel1, parallel2, pt;
|
||||
double s, step, fOffset, t, fEnd;
|
||||
int i, j;
|
||||
bool trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
|
||||
iNumShapePoints = abs(iNumShapePoints);
|
||||
if (bCurve)
|
||||
{
|
||||
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
|
||||
step = fStep;
|
||||
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
|
||||
i = iSkip; // domyślnie 0
|
||||
t = fTsBuffer[i]; // tabela wattości t dla segmentów
|
||||
fOffset = 0.1 / fLength; // pierwsze 10cm
|
||||
pos1 = FastGetPoint(t); // wektor początku segmentu
|
||||
dir = FastGetDirection(t, fOffset); // wektor kierunku
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //wektor prostopadły
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
if (iEnd == 0)
|
||||
iEnd = iSegCount;
|
||||
fEnd = fLength * double(iEnd) / double(iSegCount);
|
||||
m2 = s / fEnd;
|
||||
jmm2 = 1.0 - m2;
|
||||
while (i < iEnd)
|
||||
{
|
||||
++i; // kolejny punkt łamanej
|
||||
s += step; // końcowa pozycja segmentu [m]
|
||||
m1 = m2;
|
||||
jmm1 = jmm2; // stara pozycja
|
||||
m2 = s / fEnd;
|
||||
jmm2 = 1.0 - m2; // nowa pozycja
|
||||
if (i == iEnd)
|
||||
{ // gdy przekroczyliśmy koniec - stąd dziury w torach...
|
||||
step -= (s - fEnd); // jeszcze do wyliczenia mapowania potrzebny
|
||||
s = fEnd;
|
||||
// i=iEnd; //20/5 ma dawać 4
|
||||
m2 = 1.0;
|
||||
jmm2 = 0.0;
|
||||
}
|
||||
t = fTsBuffer[i]; // szybsze od GetTFromS(s);
|
||||
pos2 = FastGetPoint(t);
|
||||
dir = FastGetDirection(t, fOffset); // nowy wektor kierunku
|
||||
// parallel2=Normalize(CrossProduct(dir,vector3(0,1,0)));
|
||||
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
if (trapez)
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{ // współrzędne początku
|
||||
pt = parallel1 * (jmm1 * (ShapePoints[j].x - fOffsetX) +
|
||||
m1 * ShapePoints[j + iNumShapePoints].x) +
|
||||
pos1;
|
||||
pt.y += jmm1 * ShapePoints[j].y + m1 * ShapePoints[j + iNumShapePoints].y;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na początku odcinka
|
||||
Vert++;
|
||||
// dla trapezu drugi koniec ma inne współrzędne
|
||||
pt = parallel2 * (jmm2 * (ShapePoints[j].x - fOffsetX) +
|
||||
m2 * ShapePoints[j + iNumShapePoints].x) +
|
||||
pos2;
|
||||
pt.y += jmm2 * ShapePoints[j].y + m2 * ShapePoints[j + iNumShapePoints].y;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na końcu odcinka
|
||||
Vert++;
|
||||
}
|
||||
pos1 = pos2;
|
||||
parallel1 = parallel2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // gdy prosty
|
||||
pos1 = FastGetPoint((fStep * iSkip) / fLength);
|
||||
pos2 = FastGetPoint_1();
|
||||
dir = GetDirection();
|
||||
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0)));
|
||||
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
|
||||
if (trapez)
|
||||
for (j = 0; j < iNumShapePoints; j++)
|
||||
{
|
||||
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
|
||||
pt.y += ShapePoints[j].y;
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na początku odcinka
|
||||
Vert++;
|
||||
pt = parallel1 * (ShapePoints[j + iNumShapePoints].x - fOffsetX) +
|
||||
pos2; // odsunięcie
|
||||
pt.y += ShapePoints[j + iNumShapePoints].y; // wysokość
|
||||
Vert->x = pt.x;
|
||||
Vert->y = pt.y;
|
||||
Vert->z = pt.z; // punkt na końcu odcinka
|
||||
Vert++;
|
||||
}
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
23
Segment.h
23
Segment.h
@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "VBO.h"
|
||||
#include "dumb3d.h"
|
||||
#include "Classes.h"
|
||||
#include "usefull.h"
|
||||
|
||||
using namespace Math3D;
|
||||
|
||||
@@ -61,8 +62,6 @@ class TSegment
|
||||
double fDirection = 0.0; // Ra: kąt prostego w planie; dla łuku kąt od Point1
|
||||
double fStoop = 0.0; // Ra: kąt wzniesienia; dla łuku od Point1
|
||||
vector3 vA, vB, vC; // współczynniki wielomianów trzeciego stopnia vD==Point1
|
||||
// TSegment *pPrev; //odcinek od strony punktu 1 - w segmencie, żeby nie skakać na zwrotnicach
|
||||
// TSegment *pNext; //odcinek od strony punktu 2
|
||||
TTrack *pOwner = nullptr; // wskaźnik na właściciela
|
||||
double fAngle[2]; // kąty zakończenia drogi na przejazdach
|
||||
|
||||
@@ -71,12 +70,8 @@ class TSegment
|
||||
double GetTFromS(double s);
|
||||
vector3 RaInterpolate(double t);
|
||||
vector3 RaInterpolate0(double t);
|
||||
// TSegment *segNeightbour[2]; //sąsiednie odcinki - musi być przeniesione z Track
|
||||
// int iNeightbour[2]; //do którego końca doczepiony
|
||||
public:
|
||||
bool bCurve = false;
|
||||
// int iShape; //Ra: flagi kształtu dadzą więcej możliwości optymalizacji
|
||||
// (0-Bezier,1-prosty,2/3-łuk w lewo/prawo,6/7-przejściowa w lewo/prawo)
|
||||
TSegment(TTrack *owner);
|
||||
~TSegment();
|
||||
bool Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1 = 0,
|
||||
@@ -109,21 +104,16 @@ class TSegment
|
||||
{
|
||||
return Point2;
|
||||
};
|
||||
inline double GetRoll(double s)
|
||||
inline double GetRoll(double const Distance)
|
||||
{
|
||||
s /= fLength;
|
||||
return ((1.0 - s) * fRoll1 + s * fRoll2);
|
||||
return interpolate( fRoll1, fRoll2, Distance / fLength );
|
||||
}
|
||||
void GetRolls(double &r1, double &r2)
|
||||
{ // pobranie przechyłek (do generowania trójkątów)
|
||||
r1 = fRoll1;
|
||||
r2 = fRoll2;
|
||||
}
|
||||
void RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength,
|
||||
int iSkip = 0, int iQualityFactor = 1, vector3 **p = NULL, bool bRender = true);
|
||||
void RenderSwitchRail(const vector6 *ShapePoints1, const vector6 *ShapePoints2,
|
||||
int iNumShapePoints, double fTextureLength, int iSkip = 0,
|
||||
double fOffsetX = 0.0f);
|
||||
void RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, bool Onlypositions = false, vector3 **p = nullptr, bool bRender = true);
|
||||
void Render();
|
||||
inline double GetLength()
|
||||
{
|
||||
@@ -143,15 +133,10 @@ class TSegment
|
||||
{
|
||||
return fTsBuffer ? iSegCount : 1;
|
||||
};
|
||||
void RaRenderLoft(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
|
||||
double fTextureLength, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0);
|
||||
void RaAnimate(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
|
||||
double fTextureLength, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0);
|
||||
void AngleSet(int i, double a)
|
||||
{
|
||||
fAngle[i] = a;
|
||||
};
|
||||
void Rollment(double w1, double w2); // poprawianie przechyłki
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
2
Track.h
2
Track.h
@@ -256,7 +256,7 @@ class TTrack : public Resource
|
||||
void RaAssign(TGroundNode *gn, TAnimContainer *ac);
|
||||
void RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined);
|
||||
void RaAnimListAdd(TTrack *t);
|
||||
TTrack * RaAnimate();
|
||||
TTrack * RaAnimate(GLuint const Vertexbuffer = -1);
|
||||
|
||||
void RadioStop();
|
||||
void AxleCounter(int i, TDynamicObject *o)
|
||||
|
||||
607
Traction.cpp
607
Traction.cpp
@@ -116,25 +116,22 @@ void TTraction::Optimize()
|
||||
uiDisplayList = glGenLists(1);
|
||||
glNewList(uiDisplayList, GL_COMPILE);
|
||||
|
||||
GfxRenderer.Bind(0);
|
||||
// glColor3ub(0,0,0); McZapkie: to do render
|
||||
|
||||
// glPushMatrix();
|
||||
// glTranslatef(pPosition.x,pPosition.y,pPosition.z);
|
||||
|
||||
if (Wires != 0)
|
||||
{
|
||||
// Dlugosc odcinka trakcji 'Winger
|
||||
double ddp = hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z);
|
||||
|
||||
double ddp = std::hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z);
|
||||
if (Wires == 2)
|
||||
WireOffset = 0;
|
||||
// Przewoz jezdny 1 'Marcin
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(pPoint1.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pPoint1.y,
|
||||
pPoint1.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
glVertex3f(pPoint2.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pPoint2.y,
|
||||
pPoint2.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
glVertex3f(
|
||||
pPoint1.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset,
|
||||
pPoint1.y,
|
||||
pPoint1.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
glVertex3f(
|
||||
pPoint2.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset,
|
||||
pPoint2.y,
|
||||
pPoint2.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
glEnd();
|
||||
// Nie wiem co 'Marcin
|
||||
Math3D::vector3 pt1, pt2, pt3, pt4, v1, v2;
|
||||
@@ -146,24 +143,25 @@ void TTraction::Optimize()
|
||||
float f = step;
|
||||
float mid = 0.5;
|
||||
float t;
|
||||
|
||||
// Przewod nosny 'Marcin
|
||||
if (Wires != 1)
|
||||
if (Wires > 1)
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(pPoint3.x, pPoint3.y, pPoint3.z);
|
||||
for (int i = 0; i < iNumSections - 1; i++)
|
||||
for (int i = 0; i < iNumSections - 1; ++i)
|
||||
{
|
||||
pt3 = pPoint3 + v1 * f;
|
||||
t = (1 - fabs(f - mid) * 2);
|
||||
t = (1 - std::fabs(f - mid) * 2);
|
||||
if ((Wires < 4) || ((i != 0) && (i != iNumSections - 2)))
|
||||
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference, pt3.z);
|
||||
glVertex3f(
|
||||
pt3.x,
|
||||
pt3.y - std::sqrt(t) * fHeightDifference,
|
||||
pt3.z);
|
||||
f += step;
|
||||
}
|
||||
glVertex3f(pPoint4.x, pPoint4.y, pPoint4.z);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Drugi przewod jezdny 'Winger
|
||||
if (Wires > 2)
|
||||
{
|
||||
@@ -181,14 +179,17 @@ void TTraction::Optimize()
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(pPoint3.x, pPoint3.y - 0.65f * fHeightDifference, pPoint3.z);
|
||||
for (int i = 0; i < iNumSections - 1; i++)
|
||||
for (int i = 0; i < iNumSections - 1; ++i)
|
||||
{
|
||||
pt3 = pPoint3 + v1 * f;
|
||||
t = (1 - fabs(f - mid) * 2);
|
||||
t = (1 - std::fabs(f - mid) * 2);
|
||||
glVertex3f(
|
||||
pt3.x,
|
||||
pt3.y - sqrt(t) * fHeightDifference -
|
||||
((i == 0) || (i == iNumSections - 2) ? 0.25f * fHeightDifference : +0.05),
|
||||
pt3.y - std::sqrt( t ) * fHeightDifference - (
|
||||
( ( i == 0 )
|
||||
|| ( i == iNumSections - 2 ) ) ?
|
||||
0.25f * fHeightDifference :
|
||||
0.05 ),
|
||||
pt3.z);
|
||||
f += step;
|
||||
}
|
||||
@@ -202,36 +203,47 @@ void TTraction::Optimize()
|
||||
if (Wires != 1)
|
||||
{
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < iNumSections - 1; i++)
|
||||
for (int i = 0; i < iNumSections - 1; ++i)
|
||||
{
|
||||
float flo, flo1;
|
||||
flo = (Wires == 4 ? 0.25f * fHeightDifference : 0);
|
||||
flo1 = (Wires == 4 ? +0.05 : 0);
|
||||
pt3 = pPoint3 + v1 * f;
|
||||
pt4 = pPoint1 + v2 * f;
|
||||
t = (1 - fabs(f - mid) * 2);
|
||||
t = (1 - std::fabs(f - mid) * 2);
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference -
|
||||
((i == 0) || (i == iNumSections - 2) ? flo : flo1),
|
||||
pt3.z);
|
||||
glVertex3f(pt4.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pt4.y,
|
||||
pt4.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
glVertex3f(
|
||||
pt3.x,
|
||||
pt3.y - std::sqrt(t) * fHeightDifference - ((i == 0) || (i == iNumSections - 2) ? flo : flo1),
|
||||
pt3.z);
|
||||
glVertex3f(
|
||||
pt4.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset,
|
||||
pt4.y,
|
||||
pt4.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference -
|
||||
((i == 0) || (i == iNumSections - 2) ? flo : flo1),
|
||||
pt3.z);
|
||||
glVertex3f(pt4.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset, pt4.y,
|
||||
pt4.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
glVertex3f(
|
||||
pt3.x,
|
||||
pt3.y - std::sqrt(t) * fHeightDifference - ((i == 0) || (i == iNumSections - 2) ? flo : flo1),
|
||||
pt3.z);
|
||||
glVertex3f(
|
||||
pt4.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset,
|
||||
pt4.y,
|
||||
pt4.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset);
|
||||
}
|
||||
if ((Wires == 4) && ((i == 1) || (i == iNumSections - 3)))
|
||||
{
|
||||
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference - 0.05, pt3.z);
|
||||
glVertex3f(pt3.x, pt3.y - sqrt(t) * fHeightDifference, pt3.z);
|
||||
glVertex3f(
|
||||
pt3.x,
|
||||
pt3.y - std::sqrt(t) * fHeightDifference - 0.05,
|
||||
pt3.z);
|
||||
glVertex3f(
|
||||
pt3.x,
|
||||
pt3.y - std::sqrt(t) * fHeightDifference,
|
||||
pt3.z);
|
||||
}
|
||||
// endif;
|
||||
f += step;
|
||||
}
|
||||
glEnd();
|
||||
@@ -249,146 +261,89 @@ void TTraction::InitCenter(vector3 Angles, vector3 pOrigin)
|
||||
void TTraction::RenderDL(float mgn) // McZapkie: mgn to odleglosc od obserwatora
|
||||
{
|
||||
// McZapkie: ustalanie przezroczystosci i koloru linii:
|
||||
if (Wires != 0 && !TestFlag(DamageFlag, 128)) // rysuj jesli sa druty i nie zerwana
|
||||
if( Wires != 0 && !TestFlag( DamageFlag, 128 ) ) // rysuj jesli sa druty i nie zerwana
|
||||
{
|
||||
// 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)
|
||||
glDisable(GL_LINE_SMOOTH); // na liniach kiepsko wygląda - robi gradient
|
||||
float linealpha = 5000 * WireThickness / (mgn + 1.0); //*WireThickness
|
||||
if (linealpha > 1.2f)
|
||||
linealpha = 1.2f; // zbyt grube nie są dobre
|
||||
glLineWidth(linealpha);
|
||||
if (linealpha > 1.0f)
|
||||
linealpha = 1.0f;
|
||||
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||
float r, g, b;
|
||||
switch (Material)
|
||||
{ // Ra: kolory podzieliłem przez 2, bo po zmianie ambient za jasne były
|
||||
// trzeba uwzględnić kierunek świecenia Słońca - tylko ze Słońcem widać kolor
|
||||
case 1:
|
||||
if (TestFlag(DamageFlag, 1))
|
||||
{
|
||||
r = 0.00000f;
|
||||
g = 0.32549f;
|
||||
b = 0.2882353f; // zielona miedź
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 0.35098f;
|
||||
g = 0.22549f;
|
||||
b = 0.1f; // czerwona miedź
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (TestFlag(DamageFlag, 1))
|
||||
{
|
||||
r = 0.10f;
|
||||
g = 0.10f;
|
||||
b = 0.10f; // czarne Al
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 0.25f;
|
||||
g = 0.25f;
|
||||
b = 0.25f; // srebrne Al
|
||||
}
|
||||
break;
|
||||
// tymczasowo pokazanie zasilanych odcinków
|
||||
case 4:
|
||||
r = 0.5f;
|
||||
g = 0.5f;
|
||||
b = 1.0f;
|
||||
break; // niebieskie z podłączonym zasilaniem
|
||||
case 5:
|
||||
r = 1.0f;
|
||||
g = 0.0f;
|
||||
b = 0.0f;
|
||||
break; // czerwone z podłączonym zasilaniem 1
|
||||
case 6:
|
||||
r = 0.0f;
|
||||
g = 1.0f;
|
||||
b = 0.0f;
|
||||
break; // zielone z podłączonym zasilaniem 2
|
||||
case 7:
|
||||
r = 1.0f;
|
||||
g = 1.0f;
|
||||
b = 0.0f;
|
||||
break; //żółte z podłączonym zasilaniem z obu stron
|
||||
// setup
|
||||
GfxRenderer.Bind( 0 );
|
||||
if( !Global::bSmoothTraction ) {
|
||||
// na liniach kiepsko wygląda - robi gradient
|
||||
::glDisable( GL_LINE_SMOOTH );
|
||||
}
|
||||
if (DebugModeFlag)
|
||||
if (hvParallel)
|
||||
{ // jeśli z bieżnią wspólną, to dodatkowo przyciemniamy
|
||||
r *= 0.6f;
|
||||
g *= 0.6f;
|
||||
b *= 0.6f;
|
||||
}
|
||||
#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.0f)
|
||||
linealpha = 1.0f; // trzeba ograniczyć do <=1
|
||||
glColor4f(r, g, b, linealpha);
|
||||
float linealpha = 5000 * WireThickness / ( mgn + 1.0 ); //*WireThickness
|
||||
linealpha = std::min( 1.2f, linealpha ); // zbyt grube nie są dobre
|
||||
::glLineWidth( linealpha );
|
||||
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||
float
|
||||
red{ 0.0f },
|
||||
green{ 0.0f },
|
||||
blue{ 0.0f };
|
||||
wire_color( red, green, blue );
|
||||
::glColor4f( red, green, blue, linealpha );
|
||||
// draw code
|
||||
if (!uiDisplayList)
|
||||
Optimize(); // generowanie DL w miarę potrzeby
|
||||
glCallList(uiDisplayList);
|
||||
glLineWidth(1.0);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
// glEnable(GL_LIGHTING); //bez tego się modele nie oświetlają
|
||||
::glCallList(uiDisplayList);
|
||||
// cleanup
|
||||
::glLineWidth(1.0);
|
||||
::glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
// przygotowanie tablic do skopiowania do VBO (zliczanie wierzchołków)
|
||||
int TTraction::RaArrayPrepare()
|
||||
{ // przygotowanie tablic do skopiowania do VBO (zliczanie wierzchołków)
|
||||
// if (bVisible) //o ile w ogóle widać
|
||||
switch (Wires)
|
||||
{
|
||||
case 1:
|
||||
iLines = 2;
|
||||
break;
|
||||
case 2:
|
||||
iLines = iNumSections ? 4 * (iNumSections)-2 + 2 : 4;
|
||||
break;
|
||||
case 3:
|
||||
iLines = iNumSections ? 4 * (iNumSections)-2 + 4 : 6;
|
||||
break;
|
||||
case 4:
|
||||
iLines = iNumSections ? 4 * (iNumSections)-2 + 6 : 8;
|
||||
break;
|
||||
default:
|
||||
iLines = 0;
|
||||
{
|
||||
// jezdny
|
||||
iLines = 2;
|
||||
// przewod nosny
|
||||
if( Wires > 1 ) {
|
||||
iLines += 2 + (
|
||||
Wires < 4 ?
|
||||
std::max( 0, iNumSections - 1 ) :
|
||||
( iNumSections > 2 ?
|
||||
std::max( 0, iNumSections - 1 - 2 ) :
|
||||
std::max( 0, iNumSections - 1 - 1 ) ) );
|
||||
}
|
||||
// drugi przewod jezdny
|
||||
if( Wires > 2 ) {
|
||||
iLines += 2;
|
||||
}
|
||||
if( Wires == 4 ) {
|
||||
iLines += 2 + std::max( 0, iNumSections - 1 );
|
||||
}
|
||||
// przewody pionowe (wieszaki)
|
||||
if( Wires > 1 ) {
|
||||
iLines += 2 * ( std::max( 0, iNumSections - 1 ) );
|
||||
if( ( Wires == 4 )
|
||||
&&( iNumSections > 0 ) ) {
|
||||
iLines += (
|
||||
iNumSections > 4 ?
|
||||
4 :
|
||||
2 );
|
||||
}
|
||||
}
|
||||
// else iLines=0;
|
||||
return iLines;
|
||||
};
|
||||
|
||||
void TTraction::RaArrayFill(CVertNormTex *Vert)
|
||||
{ // wypełnianie tablic VBO
|
||||
CVertNormTex *old = Vert;
|
||||
double ddp = hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z);
|
||||
double ddp = std::hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z);
|
||||
if (Wires == 2)
|
||||
WireOffset = 0;
|
||||
// jezdny
|
||||
Vert->x = pPoint1.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
|
||||
Vert->x = pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
|
||||
Vert->y = pPoint1.y;
|
||||
Vert->z = pPoint1.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
|
||||
Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
|
||||
++Vert;
|
||||
Vert->x = pPoint2.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
|
||||
Vert->x = pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
|
||||
Vert->y = pPoint2.y;
|
||||
Vert->z = pPoint2.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
|
||||
Vert->z = pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
|
||||
++Vert;
|
||||
// Nie wiem co 'Marcin
|
||||
Math3D::vector3 pt1, pt2, pt3, pt4, v1, v2;
|
||||
v1 = pPoint4 - pPoint3;
|
||||
v2 = pPoint2 - pPoint1;
|
||||
float step = 0;
|
||||
if (iNumSections > 0)
|
||||
if( iNumSections > 0 )
|
||||
step = 1.0f / (float)iNumSections;
|
||||
float f = step;
|
||||
float mid = 0.5;
|
||||
@@ -400,18 +355,18 @@ void TTraction::RaArrayFill(CVertNormTex *Vert)
|
||||
Vert->y = pPoint3.y;
|
||||
Vert->z = pPoint3.z;
|
||||
++Vert;
|
||||
for (int i = 0; i < iNumSections - 1; i++)
|
||||
for (int i = 0; i < iNumSections - 1; ++i)
|
||||
{
|
||||
pt3 = pPoint3 + v1 * f;
|
||||
t = (1 - fabs(f - mid) * 2);
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - sqrt(t) * fHeightDifference;
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
Vert->x = pt3.x; // drugi raz, bo nie jest line_strip
|
||||
Vert->y = pt3.y - sqrt(t) * fHeightDifference;
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
t = (1 - std::fabs(f - mid) * 2);
|
||||
if( ( Wires < 4 )
|
||||
|| ( ( i != 0 )
|
||||
&& ( i != iNumSections - 2 ) ) ) {
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference;
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
}
|
||||
f += step;
|
||||
}
|
||||
Vert->x = pPoint4.x;
|
||||
@@ -420,7 +375,7 @@ void TTraction::RaArrayFill(CVertNormTex *Vert)
|
||||
++Vert;
|
||||
}
|
||||
// Drugi przewod jezdny 'Winger
|
||||
if (Wires == 3)
|
||||
if (Wires > 2)
|
||||
{
|
||||
Vert->x = pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
|
||||
Vert->y = pPoint1.y;
|
||||
@@ -431,124 +386,145 @@ void TTraction::RaArrayFill(CVertNormTex *Vert)
|
||||
Vert->z = pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
|
||||
++Vert;
|
||||
}
|
||||
|
||||
f = step;
|
||||
// Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
|
||||
if (Wires > 1)
|
||||
{
|
||||
for (int i = 0; i < iNumSections - 1; i++)
|
||||
{
|
||||
|
||||
if( Wires == 4 ) {
|
||||
Vert->x = pPoint3.x;
|
||||
Vert->y = pPoint3.y - 0.65f * fHeightDifference;
|
||||
Vert->z = pPoint3.z;
|
||||
++Vert;
|
||||
for( int i = 0; i < iNumSections - 1; ++i ) {
|
||||
pt3 = pPoint3 + v1 * f;
|
||||
pt4 = pPoint1 + v2 * f;
|
||||
t = (1 - fabs(f - mid) * 2);
|
||||
t = ( 1 - std::fabs( f - mid ) * 2 );
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - sqrt(t) * fHeightDifference;
|
||||
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - (
|
||||
( ( i == 0 )
|
||||
|| ( i == iNumSections - 2 ) ) ?
|
||||
0.25f * fHeightDifference :
|
||||
0.05 );
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
Vert->x = pt4.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
|
||||
Vert->y = pt4.y;
|
||||
Vert->z = pt4.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vert->x = pt4.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
|
||||
Vert->y = pt4.y;
|
||||
Vert->z = pt4.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
|
||||
}
|
||||
++Vert;
|
||||
f += step;
|
||||
}
|
||||
Vert->x = pPoint4.x;
|
||||
Vert->y = pPoint4.y - 0.65f * fHeightDifference;
|
||||
Vert->z = pPoint4.z;
|
||||
}
|
||||
f = step;
|
||||
|
||||
// Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
|
||||
if (Wires > 1)
|
||||
{
|
||||
for (int i = 0; i < iNumSections - 1; ++i)
|
||||
{
|
||||
float flo, flo1;
|
||||
flo = ( Wires == 4 ? 0.25f * fHeightDifference : 0 );
|
||||
flo1 = ( Wires == 4 ? +0.05 : 0 );
|
||||
pt3 = pPoint3 + v1 * f;
|
||||
pt4 = pPoint1 + v2 * f;
|
||||
t = (1 - std::fabs(f - mid) * 2);
|
||||
|
||||
if( ( i % 2 ) == 0 ) {
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 );
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
Vert->x = pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
|
||||
Vert->y = pt4.y;
|
||||
Vert->z = pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
|
||||
++Vert;
|
||||
}
|
||||
else {
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 );
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
Vert->x = pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
|
||||
Vert->y = pt4.y;
|
||||
Vert->z = pt4.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
|
||||
++Vert;
|
||||
}
|
||||
if( ( ( Wires == 4 )
|
||||
&& ( ( i == 1 )
|
||||
|| ( i == iNumSections - 3 ) ) ) ) {
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05;
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
Vert->x = pt3.x;
|
||||
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference;
|
||||
Vert->z = pt3.z;
|
||||
++Vert;
|
||||
}
|
||||
f += step;
|
||||
}
|
||||
}
|
||||
if ((Vert - old) != iLines)
|
||||
WriteLog("!!! Wygenerowano punktów " + std::to_string(Vert - old) + ", powinno być " +
|
||||
std::to_string(iLines));
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
// setup
|
||||
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)
|
||||
glDisable(GL_LINE_SMOOTH); // na liniach kiepsko wygląda - robi gradient
|
||||
float linealpha = 5000 * WireThickness / (mgn + 1.0); //*WireThickness
|
||||
if (linealpha > 1.2f)
|
||||
linealpha = 1.2f; // zbyt grube nie są dobre
|
||||
glLineWidth(linealpha);
|
||||
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||
float r, g, b;
|
||||
switch (Material)
|
||||
{ // Ra: kolory podzieliłem przez 2, bo po zmianie ambient za jasne były
|
||||
// trzeba uwzględnić kierunek świecenia Słońca - tylko ze Słońcem widać kolor
|
||||
case 1:
|
||||
if (TestFlag(DamageFlag, 1))
|
||||
{
|
||||
r = 0.00000f;
|
||||
g = 0.32549f;
|
||||
b = 0.2882353f; // zielona miedź
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 0.35098f;
|
||||
g = 0.22549f;
|
||||
b = 0.1f; // czerwona miedź
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (TestFlag(DamageFlag, 1))
|
||||
{
|
||||
r = 0.10f;
|
||||
g = 0.10f;
|
||||
b = 0.10f; // czarne Al
|
||||
}
|
||||
else
|
||||
{
|
||||
r = 0.25f;
|
||||
g = 0.25f;
|
||||
b = 0.25f; // srebrne Al
|
||||
}
|
||||
break;
|
||||
// tymczasowo pokazanie zasilanych odcinków
|
||||
case 4:
|
||||
r = 0.5f;
|
||||
g = 0.5f;
|
||||
b = 1.0f;
|
||||
break; // niebieskie z podłączonym zasilaniem
|
||||
case 5:
|
||||
r = 1.0f;
|
||||
g = 0.0f;
|
||||
b = 0.0f;
|
||||
break; // czerwone z podłączonym zasilaniem 1
|
||||
case 6:
|
||||
r = 0.0f;
|
||||
g = 1.0f;
|
||||
b = 0.0f;
|
||||
break; // zielone z podłączonym zasilaniem 2
|
||||
case 7:
|
||||
r = 1.0f;
|
||||
g = 1.0f;
|
||||
b = 0.0f;
|
||||
break; //żółte z podłączonym zasilaniem z obu stron
|
||||
if( !Global::bSmoothTraction ) {
|
||||
// na liniach kiepsko wygląda - robi gradient
|
||||
::glDisable( GL_LINE_SMOOTH );
|
||||
}
|
||||
#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.0f)
|
||||
linealpha = 1.0f; // trzeba ograniczyć do <=1
|
||||
glColor4f(r, g, b, linealpha);
|
||||
glDrawArrays(GL_LINES, iPtr, iLines);
|
||||
glLineWidth(1.0);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_LIGHTING); // bez tego się modele nie oświetlają
|
||||
float linealpha = 5000 * WireThickness / (mgn + 1.0); //*WireThickness
|
||||
linealpha = std::min( 1.2f, linealpha ); // zbyt grube nie są dobre
|
||||
::glLineWidth(linealpha);
|
||||
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||
float
|
||||
red{ 0.0f },
|
||||
green{ 0.0f },
|
||||
blue{ 0.0f };
|
||||
wire_color( red, green, blue );
|
||||
::glColor4f(red, green, blue, linealpha);
|
||||
// draw code
|
||||
// jezdny
|
||||
::glDrawArrays( GL_LINE_STRIP, iPtr, 2 );
|
||||
iPtr += 2;
|
||||
// przewod nosny
|
||||
if( Wires > 1 ) {
|
||||
auto const piececount = 2 + (
|
||||
Wires < 4 ?
|
||||
std::max( 0 , iNumSections - 1 ) :
|
||||
( iNumSections > 2 ?
|
||||
std::max( 0, iNumSections - 1 - 2 ) :
|
||||
std::max( 0, iNumSections - 1 - 1 ) ) );
|
||||
::glDrawArrays( GL_LINE_STRIP, iPtr, piececount );
|
||||
iPtr += piececount;
|
||||
}
|
||||
// drugi przewod jezdny
|
||||
if( Wires > 2 ) {
|
||||
::glDrawArrays( GL_LINE_STRIP, iPtr, 2 );
|
||||
iPtr += 2;
|
||||
}
|
||||
if( Wires == 4 ) {
|
||||
auto const piececount = 2 + std::max( 0, iNumSections - 1 );
|
||||
::glDrawArrays( GL_LINE_STRIP, iPtr, piececount );
|
||||
iPtr += piececount;
|
||||
}
|
||||
// przewody pionowe (wieszaki)
|
||||
if( Wires != 1 ) {
|
||||
auto piececount = 2 * std::max( 0, iNumSections - 1 );
|
||||
if( ( Wires == 4 )
|
||||
&& ( iNumSections > 0 ) ) {
|
||||
piececount += (
|
||||
iNumSections > 4 ?
|
||||
4 :
|
||||
2 );
|
||||
}
|
||||
if( piececount > 0 ) {
|
||||
::glDrawArrays( GL_LINES, iPtr, piececount );
|
||||
iPtr += piececount;
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
::glLineWidth(1.0);
|
||||
::glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -619,11 +595,16 @@ void TTraction::ResistanceCalc(int d, double r, TTractionPowerSource *ps)
|
||||
else
|
||||
ps = psPower[d ^ 1]; // zasilacz od przeciwnej strony niż idzie analiza
|
||||
d = iNext[d]; // kierunek
|
||||
// double r; //sumaryczna rezystancja
|
||||
#ifdef EU07_USE_OLD_TRACTIONPOWER_CODE
|
||||
if (DebugModeFlag) // tylko podczas testów
|
||||
Material = 4; // pokazanie, że to przęsło ma podłączone zasilanie
|
||||
while (t ? !t->psPower[d] : false) // jeśli jest jakiś kolejny i nie ma ustalonego zasilacza
|
||||
#else
|
||||
PowerState = 4;
|
||||
#endif
|
||||
while( ( t != nullptr )
|
||||
&& ( t->psPower[d] == nullptr ) ) // jeśli jest jakiś kolejny i nie ma ustalonego zasilacza
|
||||
{ // ustawienie zasilacza i policzenie rezystancji zastępczej
|
||||
#ifdef EU07_USE_OLD_TRACTIONPOWER_CODE
|
||||
if (DebugModeFlag) // tylko podczas testów
|
||||
if (t->Material != 4) // przęsła zasilającego nie modyfikować
|
||||
{
|
||||
@@ -631,6 +612,19 @@ void TTraction::ResistanceCalc(int d, double r, TTractionPowerSource *ps)
|
||||
t->Material = 4; // tymczasowo, aby zmieniła kolor
|
||||
t->Material |= d ? 2 : 1; // kolor zależny od strony, z której jest zasilanie
|
||||
}
|
||||
#else
|
||||
if( t->PowerState != 4 ) {
|
||||
// przęsła zasilającego nie modyfikować
|
||||
if( t->psPowered != nullptr ) {
|
||||
|
||||
t->PowerState = 4;
|
||||
}
|
||||
else {
|
||||
// kolor zależny od strony, z której jest zasilanie
|
||||
t->PowerState |= d ? 2 : 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
t->psPower[d] = ps; // skopiowanie wskaźnika zasilacza od danej strony
|
||||
t->fResistance[d] = r; // wpisanie rezystancji w kierunku tego zasilacza
|
||||
r += t->fResistivity * Length3(t->vParametric); // doliczenie oporu kolejnego odcinka
|
||||
@@ -716,3 +710,84 @@ double TTraction::VoltageGet(double u, double i)
|
||||
return psPower[1]->CurrentGet(res + r1t) * res;
|
||||
return 0.0; // gdy nie podłączony wcale?
|
||||
};
|
||||
|
||||
void
|
||||
TTraction::wire_color( float &Red, float &Green, float &Blue ) const {
|
||||
|
||||
if( false == DebugModeFlag ) {
|
||||
switch( Material ) { // Ra: kolory podzieliłem przez 2, bo po zmianie ambient za jasne były
|
||||
// trzeba uwzględnić kierunek świecenia Słońca - tylko ze Słońcem widać kolor
|
||||
case 1: {
|
||||
if( TestFlag( DamageFlag, 1 ) ) {
|
||||
Red = 0.00000f;
|
||||
Green = 0.32549f;
|
||||
Blue = 0.2882353f; // zielona miedź
|
||||
}
|
||||
else {
|
||||
Red = 0.35098f;
|
||||
Green = 0.22549f;
|
||||
Blue = 0.1f; // czerwona miedź
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if( TestFlag( DamageFlag, 1 ) ) {
|
||||
Red = 0.10f;
|
||||
Green = 0.10f;
|
||||
Blue = 0.10f; // czarne Al
|
||||
}
|
||||
else {
|
||||
Red = 0.25f;
|
||||
Green = 0.25f;
|
||||
Blue = 0.25f; // srebrne Al
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {break; }
|
||||
}
|
||||
// w zaleźności od koloru swiatła
|
||||
Red *= Global::DayLight.ambient[ 0 ];
|
||||
Green *= Global::DayLight.ambient[ 1 ];
|
||||
Blue *= Global::DayLight.ambient[ 2 ];
|
||||
}
|
||||
else {
|
||||
// tymczasowo pokazanie zasilanych odcinków
|
||||
switch( PowerState ) {
|
||||
|
||||
case 1: {
|
||||
// czerwone z podłączonym zasilaniem 1
|
||||
Red = 1.0f;
|
||||
Green = 0.0f;
|
||||
Blue = 0.0f;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// zielone z podłączonym zasilaniem 2
|
||||
Red = 0.0f;
|
||||
Green = 1.0f;
|
||||
Blue = 0.0f;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
//żółte z podłączonym zasilaniem z obu stron
|
||||
Red = 1.0f;
|
||||
Green = 1.0f;
|
||||
Blue = 0.0f;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
// niebieskie z podłączonym zasilaniem
|
||||
Red = 0.5f;
|
||||
Green = 0.5f;
|
||||
Blue = 1.0f;
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
if( hvParallel ) { // jeśli z bieżnią wspólną, to dodatkowo przyciemniamy
|
||||
Red *= 0.6f;
|
||||
Green *= 0.6f;
|
||||
Blue *= 0.6f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,7 @@ class TTraction
|
||||
TTraction *hvParallel = nullptr; // jednokierunkowa i zapętlona lista przęseł ewentualnej bieżni wspólnej
|
||||
float fResistance[2]; // rezystancja zastępcza do punktu zasilania (0: przęsło zasilane, <0: do policzenia)
|
||||
int iTries = 0;
|
||||
// bool bVisible;
|
||||
// DWORD dwFlags;
|
||||
int PowerState{ 0 }; // type of incoming power, if any
|
||||
|
||||
void Optimize();
|
||||
|
||||
@@ -78,5 +77,7 @@ class TTraction
|
||||
void ResistanceCalc(int d = -1, double r = 0, TTractionPowerSource *ps = NULL);
|
||||
void PowerSet(TTractionPowerSource *ps);
|
||||
double VoltageGet(double u, double i);
|
||||
private:
|
||||
void wire_color( float &Red, float &Green, float &Blue ) const;
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
28
Train.cpp
28
Train.cpp
@@ -1600,7 +1600,7 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com
|
||||
if( Train->mvControlled->EngineType != DieselEngine ) {
|
||||
if( Train->mvControlled->MainSwitch( true ) ) {
|
||||
// side-effects
|
||||
Train->mvControlled->ConverterSwitch( Train->ggConverterButton.GetValue() > 0.5 );
|
||||
Train->mvControlled->ConverterSwitch( ( Train->ggConverterButton.GetValue() > 0.5 ) || ( Train->mvControlled->ConverterStart == start::automatic ) );
|
||||
Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 );
|
||||
}
|
||||
}
|
||||
@@ -1636,6 +1636,11 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com
|
||||
|
||||
void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Train->mvControlled->ConverterStart == start::automatic ) {
|
||||
// let the automatic thing do its automatic thing...
|
||||
return;
|
||||
}
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
||||
if( ( false == Train->mvControlled->ConverterAllow )
|
||||
@@ -3680,7 +3685,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
// TODO: check whether it should affect entire consist for EMU
|
||||
// TODO: check whether it should happen if there's power supplied alternatively through hvcouplers
|
||||
// TODO: potentially move this to the mover module, as there isn't much reason to have this dependent on the operator presence
|
||||
mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3711,7 +3716,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
{
|
||||
mvControlled->ConvOvldFlag = true;
|
||||
if (mvControlled->TrainType != dt_EZT)
|
||||
mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? command_range::unit : command_range::local ) );
|
||||
mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range::unit : range::local ) );
|
||||
}
|
||||
else if( fConverterTimer >= fConverterPrzekaznik ) {
|
||||
// changed switch from always true to take into account state of the compressor switch
|
||||
@@ -4440,9 +4445,10 @@ bool TTrain::Update( double const Deltatime )
|
||||
tmp = DynamicObject->PrevConnected;
|
||||
|
||||
if (tmp)
|
||||
if (tmp->MoverParameters->Mains)
|
||||
if ( mvControlled->Battery || mvControlled->ConverterFlag )
|
||||
{
|
||||
btLampkaWylSzybkiB.TurnOn();
|
||||
btLampkaWylSzybkiB.Turn( tmp->MoverParameters->Mains );
|
||||
|
||||
btLampkaOporyB.Turn(tmp->MoverParameters->ResistorsFlagCheck());
|
||||
btLampkaBezoporowaB.Turn(
|
||||
tmp->MoverParameters->ResistorsFlagCheck() ||
|
||||
@@ -5312,7 +5318,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
switch (LampkaUniversal3_typ)
|
||||
{
|
||||
case 0:
|
||||
btLampkaUniversal3.Turn(mvControlled->Battery);
|
||||
btLampkaUniversal3.Turn( mvControlled->Battery || mvControlled->ConverterFlag );
|
||||
break;
|
||||
case 1:
|
||||
btLampkaUniversal3.Turn(mvControlled->Mains);
|
||||
@@ -5796,14 +5802,12 @@ bool TTrain::CabChange(int iDirection)
|
||||
DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName +
|
||||
".mmd"))
|
||||
{ // zmiana kabiny w ramach tego samego pojazdu
|
||||
DynamicObject->MoverParameters
|
||||
->CabActivisation(); // załączenie rozrządu (wirtualne kabiny)
|
||||
DynamicObject->MoverParameters->CabActivisation(); // załączenie rozrządu (wirtualne kabiny)
|
||||
DynamicObject->Mechanik->CheckVehicles( Change_direction );
|
||||
return true; // udało się zmienić kabinę
|
||||
}
|
||||
DynamicObject->MoverParameters->CabActivisation(); // aktywizacja
|
||||
// poprzedniej, bo
|
||||
// jeszcze nie wiadomo,
|
||||
// czy jakiś pojazd jest
|
||||
// aktywizacja poprzedniej, bo jeszcze nie wiadomo, czy jakiś pojazd jest
|
||||
DynamicObject->MoverParameters->CabActivisation();
|
||||
}
|
||||
return false; // ewentualna zmiana pojazdu
|
||||
}
|
||||
|
||||
30
World.cpp
30
World.cpp
@@ -281,11 +281,10 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
Global::window = Window; // do WM_COPYDATA
|
||||
Global::pCamera = &Camera; // Ra: wskaźnik potrzebny do likwidacji drgań
|
||||
|
||||
WriteLog("\nStarting MaSzyna rail vehicle simulator.");
|
||||
WriteLog( "Release " + Global::asRelease + " (executable: " + Global::ExecutableName + ")" );
|
||||
WriteLog("Online documentation and additional files on http://eu07.pl");
|
||||
WriteLog("Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, "
|
||||
"ShaXbee, Oli_EU, youBy, KURS90, Ra, hunter, szociu, Stele, Q, firleju and others\n");
|
||||
WriteLog( "\nStarting MaSzyna rail vehicle simulator (release: " + Global::asVersion + ")" );
|
||||
WriteLog( "For online documentation and additional files refer to: http://eu07.pl");
|
||||
WriteLog( "Authors: Marcin_EU, McZapkie, ABu, Winger, Tolaris, nbmx, OLO_EU, Bart, Quark-t, "
|
||||
"ShaXbee, Oli_EU, youBy, KURS90, Ra, hunter, szociu, Stele, Q, firleju and others\n" );
|
||||
|
||||
UILayer.set_background( "logo" );
|
||||
|
||||
@@ -621,10 +620,6 @@ void TWorld::OnKeyDown(int cKey)
|
||||
else {
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
}
|
||||
/*
|
||||
++Global::iReCompile; // odświeżyć siatki
|
||||
// Ra: jeszcze usunąć siatki ze skompilowanych obiektów!
|
||||
*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1751,9 +1746,12 @@ TWorld::Update_UI() {
|
||||
|
||||
UITable->text_lines.emplace_back(
|
||||
Global::Bezogonkow( "| " + station + " | " + arrival + " | " + departure + " | " + vmax + " | " + tableline->StationWare, true ),
|
||||
( ( owner->iStationStart < table->StationIndex ) && ( i < table->StationIndex ) ?
|
||||
float4( 0.0f, 1.0f, 0.0f, 1.0f ) :// czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||
Global::UITextColor )
|
||||
( ( owner->iStationStart < table->StationIndex )
|
||||
&& ( i < table->StationIndex )
|
||||
&& ( time.wHour >= tableline->Dh )
|
||||
&& ( time.wMinute >= tableline->Dm ) ?
|
||||
float4( 0.0f, 1.0f, 0.0f, 1.0f ) :// czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||
Global::UITextColor )
|
||||
);
|
||||
// divider/footer
|
||||
UITable->text_lines.emplace_back( "+----------------------------+-------+-------+-----+", Global::UITextColor );
|
||||
@@ -1982,7 +1980,7 @@ TWorld::Update_UI() {
|
||||
|
||||
case( GLFW_KEY_F9 ) : {
|
||||
// informacja o wersji, sposobie wyświetlania i błędach OpenGL
|
||||
uitextline1 = Global::asVersion; // informacja o wersji
|
||||
uitextline1 = "MaSzyna " + Global::asVersion; // informacja o wersji
|
||||
if( Global::iMultiplayer ) {
|
||||
uitextline1 += " (multiplayer mode is active)";
|
||||
}
|
||||
@@ -1996,9 +1994,11 @@ TWorld::Update_UI() {
|
||||
+ GfxRenderer.Info();
|
||||
|
||||
// dump last opengl error, if any
|
||||
GLenum glerror = glGetError();
|
||||
GLenum glerror = ::glGetError();
|
||||
if( glerror != GL_NO_ERROR ) {
|
||||
Global::LastGLError = to_string( glerror ) + " (" + Global::Bezogonkow( (char *)gluErrorString( glerror ) ) + ")";
|
||||
std::string glerrorstring( (char *)::gluErrorString( glerror ) );
|
||||
win1250_to_ascii( glerrorstring );
|
||||
Global::LastGLError = std::to_string( glerror ) + " (" + glerrorstring + ")";
|
||||
}
|
||||
if( false == Global::LastGLError.empty() ) {
|
||||
uitextline3 =
|
||||
|
||||
8
dumb3d.h
8
dumb3d.h
@@ -104,14 +104,8 @@ class vector3
|
||||
return &x;
|
||||
}
|
||||
|
||||
// union
|
||||
// {
|
||||
// struct
|
||||
// {
|
||||
double x, y, z;
|
||||
// };
|
||||
// scalar_t e[3];
|
||||
// };
|
||||
|
||||
bool inline Equal(vector3 *v)
|
||||
{ // sprawdzenie odległości punktów
|
||||
if (std::fabs(x - v->x) > 0.02)
|
||||
|
||||
BIN
maszyna.rc
BIN
maszyna.rc
Binary file not shown.
@@ -431,6 +431,9 @@
|
||||
<ClInclude Include="gamepadinput.h">
|
||||
<Filter>Header Files\input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="maszyna.rc">
|
||||
|
||||
486
renderer.cpp
486
renderer.cpp
@@ -11,8 +11,12 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "renderer.h"
|
||||
#include "globals.h"
|
||||
#include "timer.h"
|
||||
#include "world.h"
|
||||
#include "data.h"
|
||||
#include "dynobj.h"
|
||||
#include "animmodel.h"
|
||||
#include "traction.h"
|
||||
#include "uilayer.h"
|
||||
#include "logs.h"
|
||||
#include "usefull.h"
|
||||
@@ -31,11 +35,11 @@ bool
|
||||
opengl_camera::visible( TDynamicObject const *Dynamic ) const {
|
||||
|
||||
// sphere test is faster than AABB, so we'll use it here
|
||||
float3 diagonal(
|
||||
Dynamic->MoverParameters->Dim.L,
|
||||
Dynamic->MoverParameters->Dim.H,
|
||||
Dynamic->MoverParameters->Dim.W );
|
||||
float const radius = diagonal.Length() * 0.5f;
|
||||
glm::vec3 diagonal(
|
||||
static_cast<float>( Dynamic->MoverParameters->Dim.L ),
|
||||
static_cast<float>( Dynamic->MoverParameters->Dim.H ),
|
||||
static_cast<float>( Dynamic->MoverParameters->Dim.W ) );
|
||||
float const radius = glm::length( diagonal ) * 0.5f;
|
||||
|
||||
return ( m_frustum.sphere_inside( Dynamic->GetPosition(), radius ) > 0.0f );
|
||||
}
|
||||
@@ -143,7 +147,7 @@ opengl_renderer::Render() {
|
||||
m_camera.update_frustum();
|
||||
|
||||
Render( &World.Environment );
|
||||
World.Ground.Render( World.Camera.Pos );
|
||||
Render( &World.Ground );
|
||||
|
||||
World.Render_Cab();
|
||||
|
||||
@@ -183,7 +187,7 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
if( Global::fFogEnd > 0 ) {
|
||||
// fog setup
|
||||
::glFogfv( GL_FOG_COLOR, Global::FogColor );
|
||||
::glFogf( GL_FOG_DENSITY, 1.0f / Global::fFogEnd );
|
||||
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / Global::fFogEnd ) );
|
||||
::glEnable( GL_FOG );
|
||||
}
|
||||
else { ::glDisable( GL_FOG ); }
|
||||
@@ -236,7 +240,7 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
{
|
||||
Bind( m_moontextureid );
|
||||
float3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
|
||||
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, 1.0f - Global::fLuminance * 0.5f );
|
||||
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 1.0 - Global::fLuminance * 0.5 ) );
|
||||
|
||||
auto const moonvector = Environment->m_moon.getDirection();
|
||||
auto const moonposition = modelview * glm::vec4( moonvector.x, moonvector.y, moonvector.z, 1.0f );
|
||||
@@ -290,15 +294,15 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( TGround *Ground ) {
|
||||
|
||||
/*
|
||||
glDisable( GL_BLEND );
|
||||
glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
|
||||
glEnable( GL_LIGHTING );
|
||||
glColor3f( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
float3 const cameraposition = float3( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
|
||||
int const camerax = std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2;
|
||||
int const cameraz = std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2;
|
||||
glm::vec3 const cameraposition( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
|
||||
int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 );
|
||||
int const cameraz = static_cast<int>( std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2 );
|
||||
int const segmentcount = 2 * static_cast<int>(std::ceil( m_drawrange * Global::fDistanceFactor / 1000.0f ));
|
||||
int const originx = std::max( 0, camerax - segmentcount / 2 );
|
||||
int const originz = std::max( 0, cameraz - segmentcount / 2 );
|
||||
@@ -312,21 +316,238 @@ opengl_renderer::Render( TGround *Ground ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
::glEnable( GL_LIGHTING );
|
||||
::glDisable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
|
||||
::glColor3f( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
return true;
|
||||
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
|
||||
|
||||
Update_Lights( Ground->m_lights );
|
||||
|
||||
Ground->CameraDirection.x = std::sin( Global::pCameraRotation ); // wektor kierunkowy
|
||||
Ground->CameraDirection.z = std::cos( Global::pCameraRotation );
|
||||
TGroundNode *node;
|
||||
// rednerowanie globalnych (nie za często?)
|
||||
for( node = Ground->srGlobal.nRenderHidden; node; node = node->nNext3 ) {
|
||||
node->RenderHidden();
|
||||
}
|
||||
// renderowanie czołgowe dla obiektów aktywnych a niewidocznych
|
||||
int n = 2 * iNumSubRects; //(2*==2km) promień wyświetlanej mapy w sektorach
|
||||
int c = Ground->GetColFromX( Global::pCameraPosition.x );
|
||||
int r = Ground->GetRowFromZ( Global::pCameraPosition.z );
|
||||
TSubRect *tmp;
|
||||
int i, j, k;
|
||||
for( j = r - n; j <= r + n; j++ ) {
|
||||
for( i = c - n; i <= c + n; i++ ) {
|
||||
if( ( tmp = Ground->FastGetSubRect( i, j ) ) != nullptr ) {
|
||||
// oznaczanie aktywnych sektorów
|
||||
tmp->LoadNodes();
|
||||
|
||||
for( node = tmp->nRenderHidden; node; node = node->nNext3 ) {
|
||||
node->RenderHidden();
|
||||
}
|
||||
// jeszcze dźwięki pojazdów by się przydały, również niewidocznych
|
||||
tmp->RenderSounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
// renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
|
||||
Ground->iRendered = 0; // ilość renderowanych sektorów
|
||||
Math3D::vector3 direction;
|
||||
for( k = 0; k < Global::iSegmentsRendered; ++k ) // sektory w kolejności odległości
|
||||
{ // przerobione na użycie SectorOrder
|
||||
i = SectorOrder[ k ].x; // na starcie oba >=0
|
||||
j = SectorOrder[ k ].y;
|
||||
do {
|
||||
// pierwszy przebieg: j<=0, i>=0; drugi: j>=0, i<=0; trzeci: j<=0, i<=0 czwarty: j>=0, i>=0;
|
||||
if( j <= 0 )
|
||||
i = -i;
|
||||
j = -j; // i oraz j musi być zmienione wcześniej, żeby continue działało
|
||||
direction = Math3D::vector3( i, 0, j ); // wektor od kamery do danego sektora
|
||||
if( Math3D::LengthSquared3( direction ) > 5 ) // te blisko są zawsze wyświetlane
|
||||
{
|
||||
direction = Math3D::SafeNormalize( direction ); // normalizacja
|
||||
if( Ground->CameraDirection.x * direction.x + Ground->CameraDirection.z * direction.z < 0.55 )
|
||||
continue; // pomijanie sektorów poza kątem patrzenia
|
||||
}
|
||||
// kwadrat kilometrowy nie zawsze, bo szkoda FPS
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].RenderVBO();
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].RenderDL();
|
||||
}
|
||||
if( ( tmp = Ground->FastGetSubRect( i + c, j + r ) ) != nullptr ) {
|
||||
if( tmp->iNodeCount ) {
|
||||
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
|
||||
Ground->pRendered[ Ground->iRendered++ ] = tmp; // tworzenie listy sektorów do renderowania
|
||||
}
|
||||
}
|
||||
} while( ( i < 0 ) || ( j < 0 ) ); // są 4 przypadki, oprócz i=j=0
|
||||
}
|
||||
|
||||
// dodać renderowanie terenu z E3D - jedno VBO jest używane dla całego modelu, chyba że jest ich więcej
|
||||
if( Global::bUseVBO ) {
|
||||
if( Global::pTerrainCompact ) {
|
||||
Global::pTerrainCompact->TerrainRenderVBO( TGroundRect::iFrameNumber );
|
||||
}
|
||||
}
|
||||
|
||||
// renderowanie nieprzezroczystych
|
||||
for( i = 0; i < Ground->iRendered; ++i ) {
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
Ground->pRendered[ i ]->RenderVBO();
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
Ground->pRendered[ i ]->RenderDL();
|
||||
}
|
||||
}
|
||||
|
||||
// regular render takes care of all solid geometry present in the scene, thus we can launch alpha parts render here
|
||||
return Render_Alpha( Ground );
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( TGroundNode *Node ) {
|
||||
|
||||
Node->SetLastUsage( Timer::GetSimulationTime() );
|
||||
|
||||
switch (Node->iType)
|
||||
{ // obiekty renderowane niezależnie od odległości
|
||||
case TP_SUBMODEL:
|
||||
TSubModel::fSquareDist = 0;
|
||||
Render( Node->smTerrain );
|
||||
return true;
|
||||
}
|
||||
|
||||
double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
|
||||
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|
||||
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Node->iType)
|
||||
{
|
||||
case TP_TRACK: {
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
if( Node->iNumVerts ) {
|
||||
Node->pTrack->RaRenderVBO( Node->iVboPtr );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Node->pTrack->Render();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case TP_MODEL: {
|
||||
Node->Model->Render( &Node->pCenter );
|
||||
return true;
|
||||
}
|
||||
case TP_MEMCELL: {
|
||||
GfxRenderer.Render( Node->MemCell );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: sprawdzic czy jest potrzebny warunek fLineThickness < 0
|
||||
if( ( Node->iFlags & 0x10 )
|
||||
|| ( Node->fLineThickness < 0 ) ) {
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( false == Global::bUseVBO ) {
|
||||
// additional setup for display lists
|
||||
if( ( Node->DisplayListID == 0 )
|
||||
|| ( Node->iVersion != Global::iReCompile ) ) { // Ra: wymuszenie rekompilacji
|
||||
Node->Compile();
|
||||
if( Global::bManageNodes )
|
||||
ResourceManager::Register( Node );
|
||||
};
|
||||
}
|
||||
|
||||
if( ( Node->iType == GL_LINES )
|
||||
|| ( Node->iType == GL_LINE_STRIP )
|
||||
|| ( Node->iType == GL_LINE_LOOP ) ) {
|
||||
// wszelkie linie są rysowane na samym końcu
|
||||
if( Node->iNumPts ) {
|
||||
// setup
|
||||
// w zaleznosci od koloru swiatla
|
||||
::glColor4ub(
|
||||
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
|
||||
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] ) ),
|
||||
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] ) ),
|
||||
static_cast<GLubyte>( std::min( 255.0, 255000 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) );
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
|
||||
// render
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
|
||||
}
|
||||
else {
|
||||
::glCallList( Node->DisplayListID );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// GL_TRIANGLE etc
|
||||
// setup
|
||||
::glColor3ub(
|
||||
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
|
||||
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
|
||||
static_cast<GLubyte>( Node->Diffuse[ 2 ] ) );
|
||||
|
||||
Bind( Node->TextureID );
|
||||
|
||||
// render
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( Node->iVboPtr >= 0 ) {
|
||||
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
if( Node->DisplayListID != 0 ) {
|
||||
::glCallList( Node->DisplayListID );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// in theory we shouldn't ever get here but, eh
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
|
||||
if( false == m_camera.visible( Dynamic ) ) {
|
||||
|
||||
Dynamic->renderme = false;
|
||||
Dynamic->renderme = m_camera.visible( Dynamic );
|
||||
if( false == Dynamic->renderme ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Dynamic->renderme = true;
|
||||
|
||||
// setup
|
||||
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
|
||||
double squaredistance = SquareMagnitude( ( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor );
|
||||
@@ -517,7 +738,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
float const anglefactor = ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
|
||||
// distance attenuation. NOTE: since it's fixed pipeline with built-in gamma correction we're using linear attenuation
|
||||
// we're capping how much effect the distance attenuation can have, otherwise the lights get too tiny at regular distances
|
||||
float const distancefactor = std::max( 0.5, ( Submodel->fSquareMaxDist - TSubModel::fSquareDist ) / ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) );
|
||||
float const distancefactor = static_cast<float>( std::max( 0.5, ( Submodel->fSquareMaxDist - TSubModel::fSquareDist ) / ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) ) );
|
||||
|
||||
if( lightlevel > 0.0f ) {
|
||||
// material configuration:
|
||||
@@ -609,6 +830,215 @@ opengl_renderer::Render( TMemCell *Memcell ) {
|
||||
::glPopAttrib();
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TGround *Ground ) {
|
||||
|
||||
// legacy version of the code:
|
||||
::glEnable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.04f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
|
||||
::glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
TGroundNode *node;
|
||||
TSubRect *tmp;
|
||||
// Ra: renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
|
||||
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
|
||||
{ // przezroczyste trójkąty w oddzielnym cyklu przed modelami
|
||||
tmp = Ground->pRendered[ i ];
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( tmp->StartVBO() ) {
|
||||
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
||||
if( node->iVboPtr >= 0 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
}
|
||||
tmp->EndVBO();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
|
||||
{ // renderowanie przezroczystych modeli oraz pojazdów
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
Ground->pRendered[ i ]->RenderAlphaVBO();
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
Ground->pRendered[ i ]->RenderAlphaDL();
|
||||
}
|
||||
}
|
||||
|
||||
::glDisable( GL_LIGHTING ); // linie nie powinny świecić
|
||||
|
||||
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
|
||||
{ // druty na końcu, żeby się nie robiły białe plamy na tle lasu
|
||||
tmp = Ground->pRendered[ i ];
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( tmp->StartVBO() ) {
|
||||
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
tmp->EndVBO();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node ); // druty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: legacy render system switch
|
||||
#define _PROBLEND
|
||||
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
|
||||
// SPOSOB NA POZBYCIE SIE RAMKI DOOKOLA TEXTURY ALPHA DLA OBIEKTOW ZAGNIEZDZONYCH W SCN JAKO
|
||||
// NODE
|
||||
|
||||
// W GROUND.H dajemy do klasy TGroundNode zmienna bool PROBLEND to samo robimy w klasie TGround
|
||||
// nastepnie podczas wczytywania textury dla TRIANGLES w TGround::AddGroundNode
|
||||
// sprawdzamy czy w nazwie jest @ i wg tego
|
||||
// ustawiamy PROBLEND na true dla wlasnie wczytywanego trojkata (kazdy trojkat jest osobnym
|
||||
// nodem)
|
||||
// nastepnie podczas renderowania w bool TGroundNode::RenderAlpha()
|
||||
// na poczatku ustawiamy standardowe GL_GREATER = 0.04
|
||||
// pozniej sprawdzamy czy jest wlaczony PROBLEND dla aktualnie renderowanego noda TRIANGLE,
|
||||
// wlasciwie dla kazdego node'a
|
||||
// i jezeli tak to odpowiedni GL_GREATER w przeciwnym wypadku standardowy 0.04
|
||||
|
||||
Node->SetLastUsage( Timer::GetSimulationTime() );
|
||||
|
||||
double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
|
||||
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|
||||
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Node->iType)
|
||||
{
|
||||
case TP_TRACTION: {
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Node->bVisible ) {
|
||||
if( Global::bUseVBO ) {
|
||||
Node->hvTraction->RenderVBO( distancesquared, Node->iVboPtr );
|
||||
}
|
||||
else {
|
||||
Node->hvTraction->RenderDL( distancesquared );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case TP_MODEL: {
|
||||
Node->Model->RenderAlpha( &Node->pCenter );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: sprawdzic czy jest potrzebny warunek fLineThickness < 0
|
||||
if( ( Node->iNumVerts && ( Node->iFlags & 0x20 ) )
|
||||
|| ( Node->iNumPts && ( Node->fLineThickness > 0 ) ) ) {
|
||||
|
||||
#ifdef _PROBLEND
|
||||
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
|
||||
{
|
||||
::glDisable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
|
||||
};
|
||||
#endif
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( false == Global::bUseVBO ) {
|
||||
// additional setup for display lists
|
||||
if( ( Node->DisplayListID == 0 )
|
||||
|| ( Node->iVersion != Global::iReCompile ) ) { // Ra: wymuszenie rekompilacji
|
||||
Node->Compile();
|
||||
if( Global::bManageNodes )
|
||||
ResourceManager::Register( Node );
|
||||
};
|
||||
}
|
||||
|
||||
bool result( false );
|
||||
|
||||
if( ( Node->iType == GL_LINES )
|
||||
|| ( Node->iType == GL_LINE_STRIP )
|
||||
|| ( Node->iType == GL_LINE_LOOP ) ) {
|
||||
// wszelkie linie są rysowane na samym końcu
|
||||
if( Node->iNumPts ) {
|
||||
// setup
|
||||
// w zaleznosci od koloru swiatla
|
||||
::glColor4ub(
|
||||
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
|
||||
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] ) ),
|
||||
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] ) ),
|
||||
static_cast<GLubyte>( std::min( 255.0, 255000 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) );
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
|
||||
// render
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
|
||||
}
|
||||
else {
|
||||
::glCallList( Node->DisplayListID );
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// GL_TRIANGLE etc
|
||||
// setup
|
||||
::glColor3ub(
|
||||
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
|
||||
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
|
||||
static_cast<GLubyte>( Node->Diffuse[ 2 ] ) );
|
||||
|
||||
Bind( Node->TextureID );
|
||||
|
||||
// render
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( Node->iVboPtr >= 0 ) {
|
||||
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
::glCallList( Node->DisplayListID );
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
// post-render cleanup
|
||||
#ifdef _PROBLEND
|
||||
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
|
||||
{
|
||||
::glEnable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.04f );
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
// in theory we shouldn't ever get here but, eh
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
|
||||
@@ -978,12 +1408,12 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
|
||||
if( environment > 0.0f ) {
|
||||
luminance *= environment;
|
||||
}
|
||||
renderlight->diffuse[ 0 ] = std::max( 0.0, scenelight.color.x - luminance );
|
||||
renderlight->diffuse[ 1 ] = std::max( 0.0, scenelight.color.y - luminance );
|
||||
renderlight->diffuse[ 2 ] = std::max( 0.0, scenelight.color.z - luminance );
|
||||
renderlight->ambient[ 0 ] = std::max( 0.0, scenelight.color.x * scenelight.intensity - luminance);
|
||||
renderlight->ambient[ 1 ] = std::max( 0.0, scenelight.color.y * scenelight.intensity - luminance );
|
||||
renderlight->ambient[ 2 ] = std::max( 0.0, scenelight.color.z * scenelight.intensity - luminance );
|
||||
renderlight->diffuse[ 0 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.x - luminance ) );
|
||||
renderlight->diffuse[ 1 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.y - luminance ) );
|
||||
renderlight->diffuse[ 2 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.z - luminance ) );
|
||||
renderlight->ambient[ 0 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.x * scenelight.intensity - luminance) );
|
||||
renderlight->ambient[ 1 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.y * scenelight.intensity - luminance ) );
|
||||
renderlight->ambient[ 2 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.z * scenelight.intensity - luminance ) );
|
||||
/*
|
||||
// NOTE: we have no simple way to determine whether the lights are falling on objects located in darker environment
|
||||
// until this issue is resolved we're disabling reduction of light strenght based on the global luminance
|
||||
@@ -994,7 +1424,7 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
|
||||
renderlight->ambient[ 1 ] = std::max( 0.0f, scenelight.color.y * scenelight.intensity );
|
||||
renderlight->ambient[ 2 ] = std::max( 0.0f, scenelight.color.z * scenelight.intensity );
|
||||
*/
|
||||
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, (0.25f * scenelight.count) / std::pow( scenelight.count, 2 ) * (scenelight.owner->DimHeadlights ? 1.25f : 1.0f) );
|
||||
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, static_cast<GLfloat>( (0.25 * scenelight.count) / std::pow( scenelight.count, 2 ) * (scenelight.owner->DimHeadlights ? 1.25 : 1.0) ) );
|
||||
::glEnable( renderlight->id );
|
||||
|
||||
renderlight->apply_intensity();
|
||||
@@ -1029,8 +1459,8 @@ opengl_renderer::Init_caps() {
|
||||
+ " Vendor: " + std::string( (char *)glGetString( GL_VENDOR ) )
|
||||
+ " OpenGL Version: " + oglversion );
|
||||
|
||||
if( !GLEW_VERSION_1_4 ) {
|
||||
ErrorLog( "Requires openGL >= 1.4" );
|
||||
if( !GLEW_VERSION_1_5 ) {
|
||||
ErrorLog( "Requires openGL >= 1.5" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,8 @@ public:
|
||||
Render( world_environment *Environment );
|
||||
bool
|
||||
Render( TGround *Ground );
|
||||
bool
|
||||
Render( TGroundNode *Node );
|
||||
bool
|
||||
Render( TDynamicObject *Dynamic );
|
||||
bool
|
||||
@@ -134,6 +136,10 @@ public:
|
||||
Render( TSubModel *Submodel );
|
||||
void
|
||||
Render( TMemCell *Memcell );
|
||||
bool
|
||||
Render_Alpha( TGround *Ground );
|
||||
bool
|
||||
Render_Alpha( TGroundNode *Node );
|
||||
bool
|
||||
Render_Alpha( TDynamicObject *Dynamic );
|
||||
bool
|
||||
|
||||
1
stdafx.h
1
stdafx.h
@@ -26,6 +26,7 @@
|
||||
#undef NOMINMAX
|
||||
#include <dbghelp.h>
|
||||
#include <direct.h>
|
||||
#include <strsafe.h>
|
||||
#endif
|
||||
// stl
|
||||
#include <cstdlib>
|
||||
|
||||
Reference in New Issue
Block a user