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

merge (incomplete)

This commit is contained in:
VB
2017-06-20 21:08:26 +02:00
61 changed files with 5275 additions and 6960 deletions

View File

@@ -411,13 +411,7 @@ TAnimModel::TAnimModel()
pModel = NULL;
iNumLights = 0;
fBlinkTimer = 0;
#ifdef EU07_USE_OLD_RENDERCODE
ReplacableSkinId[ 0 ] = 0;
ReplacableSkinId[ 1 ] = 0;
ReplacableSkinId[ 2 ] = 0;
ReplacableSkinId[ 3 ] = 0;
ReplacableSkinId[ 4 ] = 0;
#endif
for (int i = 0; i < iMaxNumLights; i++)
{
LightsOn[i] = LightsOff[i] = NULL; // normalnie nie ma
@@ -443,28 +437,7 @@ bool TAnimModel::Init(TModel3d *pNewModel)
pModel = pNewModel;
return (pModel != NULL);
}
#ifdef EU07_USE_OLD_RENDERCODE
bool TAnimModel::Init(std::string const &asName, std::string const &asReplacableTexture)
{
if (asReplacableTexture.substr(0, 1) ==
"*") // od gwiazdki zaczynają się teksty na wyświetlaczach
asText = asReplacableTexture.substr(1, asReplacableTexture.length() - 1); // zapamiętanie tekstu
else if (asReplacableTexture != "none")
ReplacableSkinId[1] =
GfxRenderer.GetTextureId( asReplacableTexture, "" );
if( ( ReplacableSkinId[ 1 ] != 0 )
&& ( GfxRenderer.Texture( ReplacableSkinId[ 1 ] ).has_alpha ) ) {
// tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych
iTexAlpha = 0x31310031;
}
else{
// tekstura nieprzezroczysta - nie renderować w cyklu
iTexAlpha = 0x30300030;
}
// przezroczystych
return (Init(TModelsManager::GetModel(asName)));
}
#else
bool TAnimModel::Init(std::string const &asName, std::string const &asReplacableTexture)
{
if (asReplacableTexture.substr(0, 1) ==
@@ -485,7 +458,6 @@ bool TAnimModel::Init(std::string const &asName, std::string const &asReplacable
// przezroczystych
return (Init(TModelsManager::GetModel(asName)));
}
#endif
bool TAnimModel::Load(cParser *parser, bool ter)
{ // rozpoznanie wpisu modelu i ustawienie świateł
@@ -622,111 +594,29 @@ void TAnimModel::RaPrepare()
// for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext) //albo osobny łańcuch
// pCurrent->UpdateModelIK(); //przeliczenie odwrotnej kinematyki
}
/*
void TAnimModel::RenderVBO(vector3 pPosition, double fAngle)
{ // sprawdza światła i rekurencyjnie renderuje TModel3d
RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli
pModel->RaRender(pPosition, fAngle, ReplacableSkinId, iTexAlpha);
}
void TAnimModel::RenderAlphaVBO(vector3 pPosition, double fAngle)
{
RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli
pModel->RaRenderAlpha(pPosition, fAngle, ReplacableSkinId, iTexAlpha);
};
void TAnimModel::RenderDL(vector3 pPosition, double fAngle)
{
RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli
pModel->Render(pPosition, fAngle, ReplacableSkinId, iTexAlpha);
}
void TAnimModel::RenderAlphaDL(vector3 pPosition, double fAngle)
{
RaPrepare();
if (pModel)
pModel->RenderAlpha(pPosition, fAngle, ReplacableSkinId, iTexAlpha);
};
*/
#ifdef EU07_USE_OLD_RENDERCODE
int TAnimModel::Flags()
{ // informacja dla TGround, czy ma być w Render, RenderAlpha, czy RenderMixed
int i = pModel ? pModel->Flags() : 0; // pobranie flag całego modelu
if (ReplacableSkinId[1] > 0) // jeśli ma wymienną teksturę 0
i |= (i & 0x01010001) * ((iTexAlpha & 1) ? 0x20 : 0x10);
// if (ReplacableSkinId[2]>0) //jeśli ma wymienną teksturę 1
// i|=(i&0x02020002)*((iTexAlpha&1)?0x10:0x08);
// if (ReplacableSkinId[3]>0) //jeśli ma wymienną teksturę 2
// i|=(i&0x04040004)*((iTexAlpha&1)?0x08:0x04);
// if (ReplacableSkinId[4]>0) //jeśli ma wymienną teksturę 3
// i|=(i&0x08080008)*((iTexAlpha&1)?0x04:0x02);
return i;
};
#else
int TAnimModel::Flags()
{ // informacja dla TGround, czy ma być w Render, RenderAlpha, czy RenderMixed
int i = pModel ? pModel->Flags() : 0; // pobranie flag całego modelu
if( m_materialdata.replacable_skins[ 1 ] > 0 ) // jeśli ma wymienną teksturę 0
i |= (i & 0x01010001) * ((m_materialdata.textures_alpha & 1) ? 0x20 : 0x10);
// if (ReplacableSkinId[2]>0) //jeśli ma wymienną teksturę 1
// i|=(i&0x02020002)*((iTexAlpha&1)?0x10:0x08);
// if (ReplacableSkinId[3]>0) //jeśli ma wymienną teksturę 2
// i|=(i&0x04040004)*((iTexAlpha&1)?0x08:0x04);
// if (ReplacableSkinId[4]>0) //jeśli ma wymienną teksturę 3
// i|=(i&0x08080008)*((iTexAlpha&1)?0x04:0x02);
return i;
};
#endif
//-----------------------------------------------------------------------------
// 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów
// 2011-03-16 funkcje renderowania z możliwością pochylania obiektów
//-----------------------------------------------------------------------------
#ifdef EU07_USE_OLD_RENDERCODE
void TAnimModel::RenderDL(vector3 *vPosition)
{
void TAnimModel::Render( vector3 const &Position ) {
RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
pModel->Render(vPosition, &vAngle, ReplacableSkinId, iTexAlpha);
GfxRenderer.Render( pModel, Material(), Position, vAngle );
};
void TAnimModel::RenderAlphaDL(vector3 *vPosition)
{
RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli
pModel->RenderAlpha(vPosition, &vAngle, ReplacableSkinId, iTexAlpha);
};
void TAnimModel::RenderVBO(vector3 *vPosition)
{
RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli
pModel->RaRender( vPosition, &vAngle, Material()->replacable_skins, Material()->textures_alpha );
};
void TAnimModel::RenderAlphaVBO(vector3 *vPosition)
{
RaPrepare();
if (pModel) // renderowanie rekurencyjne submodeli
pModel->RaRenderAlpha( vPosition, &vAngle, Material()->replacable_skins, Material()->textures_alpha );
};
#else
void TAnimModel::Render( vector3 *vPosition ) {
RaAnimate(); // jednorazowe przeliczenie animacji
void TAnimModel::RenderAlpha( vector3 const &Position ) {
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
GfxRenderer.Render( pModel, Material(), *vPosition, vAngle );
GfxRenderer.Render_Alpha( pModel, Material(), Position, vAngle );
};
void TAnimModel::RenderAlpha( vector3 *vPosition ) {
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
GfxRenderer.Render_Alpha( pModel, Material(), *vPosition, vAngle );
};
#endif
//---------------------------------------------------------------------------
bool TAnimModel::TerrainLoaded()
@@ -901,13 +791,8 @@ void TAnimModel::LightSet(int n, float v)
void TAnimModel::AnimUpdate(double dt)
{ // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane
TAnimContainer *p = TAnimModel::acAnimList;
while (p)
{ // jeśli w ogóle jest co animować
// if ((*p)->fTranslateSpeed==0.0)
// if ((*p)->fRotateSpeed==0.0)
// {//jak się naanimował, to usunąć z listy
// *p=(*p)->ListRemove(); //zwraca wskaźnik do kolejnego z listy
// }
while( p ) {
p->UpdateModel();
p = p->acAnimNext; // na razie bez usuwania z listy, bo głównie obrotnica na nią wchodzi
}

View File

@@ -12,8 +12,7 @@ http://mozilla.org/MPL/2.0/.
*/
#ifndef AnimModelH
#define AnimModelH
#pragma once
#include "Model3d.h"
#include "Texture.h"
@@ -139,11 +138,7 @@ class TAnimModel
TSubModel *LightsOn[iMaxNumLights]; // Ra: te wskaźniki powinny być w ramach TModel3d
TSubModel *LightsOff[iMaxNumLights];
vector3 vAngle; // bazowe obroty egzemplarza względem osi
#ifdef EU07_USE_OLD_RENDERCODE
int iTexAlpha; //żeby nie sprawdzać za każdym razem, dla 4 wymiennych tekstur
#else
material_data m_materialdata;
#endif
std::string asText; // tekst dla wyświetlacza znakowego
TAnimAdvanced *pAdvanced;
@@ -155,14 +150,9 @@ class TAnimModel
void RaAnimate(); // przeliczenie animacji egzemplarza
void RaPrepare(); // ustawienie animacji egzemplarza na wzorcu
public:
#ifdef EU07_USE_OLD_RENDERCODE
texture_manager::size_type ReplacableSkinId[5]; // McZapkie-020802: zmienialne skory
#endif
static TAnimContainer *acAnimList; // lista animacji z eventem, które muszą być przeliczane również bez wyświetlania
#ifndef EU07_USE_OLD_RENDERCODE
inline
material_data const *Material() const { return &m_materialdata; }
#endif
TAnimModel();
~TAnimModel();
@@ -171,20 +161,8 @@ class TAnimModel
bool Load(cParser *parser, bool ter = false);
TAnimContainer * AddContainer(char *pName);
TAnimContainer * GetContainer(char *pName);
/* void RenderDL(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
void RenderAlphaDL(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
void RenderVBO(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
void RenderAlphaVBO(vector3 pPosition = vector3(0, 0, 0), double fAngle = 0);
*/
#ifdef EU07_USE_OLD_RENDERCODE
void RenderDL( vector3 *vPosition );
void RenderAlphaDL(vector3 *vPosition);
void RenderVBO(vector3 *vPosition);
void RenderAlphaVBO(vector3 *vPosition);
#else
void Render( vector3 *vPosition );
void RenderAlpha( vector3 *vPosition );
#endif
void Render( vector3 const &Position );
void RenderAlpha( vector3 const &Position );
int Flags();
void RaAnglesSet(double a, double b, double c)
{
@@ -201,6 +179,4 @@ class TAnimModel
static void AnimUpdate(double dt);
};
//---------------------------------------------------------------------------
#endif

View File

@@ -410,21 +410,21 @@ bool TCamera::SetMatrix()
return true;
}
bool TCamera::SetMatrix( glm::mat4 &Matrix ) {
bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
Matrix = glm::rotate( Matrix, (float)-Roll, glm::vec3( 0.0f, 0.0f, 1.0f ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
Matrix = glm::rotate( Matrix, (float)-Pitch, glm::vec3( 1.0f, 0.0f, 0.0f ) );
Matrix = glm::rotate( Matrix, (float)-Yaw, glm::vec3( 0.0f, 1.0f, 0.0f ) ); // w zewnętrznym widoku: kierunek patrzenia
Matrix = glm::rotate( Matrix, -Roll, glm::dvec3( 0.0, 0.0, 1.0 ) ); // po wyłączeniu tego kręci się pojazd, a sceneria nie
Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) );
Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia
if( Type == tp_Follow ) {
Matrix *= glm::lookAt(
glm::vec3( Pos.x, Pos.y, Pos.z ),
glm::vec3( LookAt.x, LookAt.y, LookAt.z ),
glm::vec3( vUp.x, vUp.y, vUp.z ) );
glm::dvec3( Pos.x, Pos.y, Pos.z ),
glm::dvec3( LookAt.x, LookAt.y, LookAt.z ),
glm::dvec3( vUp.x, vUp.y, vUp.z ) );
}
else {
Matrix = glm::translate( Matrix, glm::vec3( -Pos.x, -Pos.y, -Pos.z ) ); // nie zmienia kierunku patrzenia
Matrix = glm::translate( Matrix, glm::dvec3( -Pos.x, -Pos.y, -Pos.z ) ); // nie zmienia kierunku patrzenia
}
Global::SetCameraPosition( Pos ); // było +pOffset

View File

@@ -58,7 +58,7 @@ class TCamera
void Update();
vector3 GetDirection();
bool SetMatrix();
bool SetMatrix(glm::mat4 &Matrix);
bool SetMatrix(glm::dmat4 &Matrix);
void SetCabMatrix( vector3 &p );
void RaLook();
void Stop();

1248
Driver.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -102,6 +102,7 @@ enum TAction
enum TSpeedPosFlag
{ // wartości dla iFlag w TSpeedPos
spNone = 0x0,
spEnabled = 0x1, // pozycja brana pod uwagę
spTrack = 0x2, // to jest tor
spReverse = 0x4, // odwrotnie
@@ -126,11 +127,11 @@ enum TSpeedPosFlag
class TSpeedPos
{ // pozycja tabeli prędkości dla AI
public:
double fDist; // aktualna odległość (ujemna gdy minięte)
double fVelNext; // prędkość obowiązująca od tego miejsca
double fSectionVelocityDist; // długość ograniczenia prędkości
double fDist{ 0.0 }; // aktualna odległość (ujemna gdy minięte)
double fVelNext{ -1.0 }; // prędkość obowiązująca od tego miejsca
double fSectionVelocityDist{ 0.0 }; // długość ograniczenia prędkości
// double fAcc;
int iFlags; // flagi typu wpisu do tabelki
int iFlags{ spNone }; // flagi typu wpisu do tabelki
// 1=istotny,2=tor,4=odwrotnie,8-zwrotnica (może się zmienić),16-stan
// zwrotnicy,32-minięty,64=koniec,128=łuk
// 0x100=event,0x200=manewrowa,0x400=przystanek,0x800=SBL,0x1000=wysłana komenda,0x2000=W5
@@ -138,8 +139,8 @@ class TSpeedPos
vector3 vPos; // współrzędne XYZ do liczenia odległości
struct
{
TTrack *trTrack; // wskaźnik na tor o zmiennej prędkości (zwrotnica, obrotnica)
TEvent *evEvent; // połączenie z eventem albo komórką pamięci
TTrack *trTrack{ nullptr }; // wskaźnik na tor o zmiennej prędkości (zwrotnica, obrotnica)
TEvent *evEvent{ nullptr }; // połączenie z eventem albo komórką pamięci
};
void CommandCheck();
@@ -166,16 +167,14 @@ extern bool WriteLogFlag; // logowanie parametrów fizycznych
class TController
{
private: // obsługa tabelki prędkości (musi mieć możliwość odhaczania stacji w rozkładzie)
TSpeedPos *sSpeedTable = nullptr; // najbliższe zmiany prędkości
int iSpeedTableSize = 16; // wielkość tabelki
int iFirst = 0; // aktualna pozycja w tabeli (modulo iSpeedTableSize)
int iLast = 0; // ostatnia wypełniona pozycja w tabeli <iFirst (modulo iSpeedTableSize)
int iTableDirection = 0; // kierunek zapełnienia tabelki względem pojazdu z AI
size_t iLast{ 0 }; // ostatnia wypełniona pozycja w tabeli <iFirst (modulo iSpeedTableSize)
int iTableDirection{ 0 }; // kierunek zapełnienia tabelki względem pojazdu z AI
std::vector<TSpeedPos> sSpeedTable;
double fLastVel = 0.0; // prędkość na poprzednio sprawdzonym torze
TTrack *tLast = nullptr; // ostatni analizowany tor
TEvent *eSignSkip = nullptr; // można pominąć ten SBL po zatrzymaniu
TSpeedPos *sSemNext = nullptr; // następny semafor na drodze zależny od trybu jazdy
TSpeedPos *sSemNextStop = nullptr; // następny semafor na drodze zależny od trybu jazdy i na stój
std::size_t SemNextIndex{ std::size_t(-1) };
std::size_t SemNextStopIndex{ std::size_t( -1 ) };
private: // parametry aktualnego składu
double fLength = 0.0; // długość składu (do wyciągania z ograniczeń)
double fMass = 0.0; // całkowita masa do liczenia stycznej składowej grawitacji
@@ -202,8 +201,7 @@ class TController
public:
double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę
// hamulca
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
private:
double fReady = 0.0; // poziom odhamowania wagonów
bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow
@@ -212,6 +210,7 @@ class TController
double deltalog = 0.05; // przyrost czasu
double LastReactionTime = 0.0;
double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi
double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations
TAction eAction = actSleep; // aktualny stan
bool HelpMeFlag = false; // wystawiane True jesli cos niedobrego sie dzieje
public:
@@ -321,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();
@@ -332,6 +333,7 @@ class TController
inline TOrders OrderCurrentGet();
inline TOrders OrderNextGet();
bool CheckVehicles(TOrders user = Wait_for_orders);
int CheckDirection();
private:
void CloseLog();
@@ -352,19 +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 *e);
void TableClear();
TEvent *TableCheckTrackEvent(double fDirection, TTrack *Track);
bool TableNotFound(TEvent const *Event) const;
// 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);
@@ -395,9 +400,9 @@ class TController
};
void MoveTo(TDynamicObject *to);
void DirectionInitial();
std::string TableText(int i);
std::string TableText(std::size_t const Index);
int CrossRoute(TTrack *tr);
void RouteSwitch(int d);
std::string OwnerName();
std::string OwnerName() const;
TMoverParameters const *Controlling() const { return mvControlling; }
};

View File

@@ -45,6 +45,11 @@ http://mozilla.org/MPL/2.0/.
#define M_2PI 6.283185307179586476925286766559;
const float maxrot = (float)(M_PI / 3.0); // 60°
std::string const TDynamicObject::MED_labels[] = {
"masa: ", "amax: ", "Fzad: ", "FmPN: ", "FmED: ", "FrED: ", "FzPN: ", "nPrF: "
};
//---------------------------------------------------------------------------
void TAnimPant::AKP_4E()
{ // ustawienie wymiarów dla pantografu AKP-4E
@@ -798,7 +803,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
btnOn = true;
}
// else btCPass2.TurnOff();
if (MoverParameters->Battery)
if (MoverParameters->Battery || MoverParameters->ConverterFlag)
{ // sygnaly konca pociagu
if (btEndSignals1.Active())
{
@@ -900,7 +905,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
// Ra: przechyłkę załatwiamy na etapie przesuwania modelu
// if (ObjSqrDist<80000) ABuModelRoll(); //przechyłki od 400m
}
if (MoverParameters->Battery)
if( MoverParameters->Battery || MoverParameters->ConverterFlag )
{ // sygnały czoła pociagu //Ra: wyświetlamy bez
// ograniczeń odległości, by były widoczne z
// daleka
@@ -1526,14 +1531,6 @@ TDynamicObject::TDynamicObject()
//}
mdModel = NULL;
mdKabina = NULL;
#ifdef EU07_USE_OLD_RENDERCODE
ReplacableSkinID[ 0 ] = 0;
ReplacableSkinID[ 1 ] = 0;
ReplacableSkinID[ 2 ] = 0;
ReplacableSkinID[ 3 ] = 0;
ReplacableSkinID[ 4 ] = 0;
iAlpha = 0x30300030; // tak gdy tekstury wymienne nie mają przezroczystości
#endif
// smWiazary[0]=smWiazary[1]=NULL;
smWahacze[0] = smWahacze[1] = smWahacze[2] = smWahacze[3] = NULL;
fWahaczeAmp = 0;
@@ -1753,52 +1750,45 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
// wylaczanie hamulca
if (ActPar.find("<>") != std::string::npos) // wylaczanie na probe hamowania naglego
{
MoverParameters->BrakeStatus |= 128; // wylacz
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
}
if (ActPar.find('0') != std::string::npos) // wylaczanie na sztywno
{
MoverParameters->BrakeStatus |= 128; // wylacz
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
MoverParameters->Hamulec->ForceEmptiness();
MoverParameters->BrakeReleaser(1); // odluznij automatycznie
}
if (ActPar.find('E') != std::string::npos) // oprozniony
{
MoverParameters->Hamulec->ForceEmptiness();
MoverParameters->BrakeReleaser(1); // odluznij automatycznie
MoverParameters->Pipe->CreatePress(0);
MoverParameters->Pipe2->CreatePress(0);
}
if (ActPar.find('Q') != std::string::npos) // oprozniony
{
// MoverParameters->Hamulec->ForceEmptiness(); //TODO: sprawdzic,
// dlaczego
// pojawia sie blad przy uzyciu tej linijki w lokomotywie
MoverParameters->BrakeReleaser(1); // odluznij automatycznie
MoverParameters->Hamulec->ForceEmptiness();
MoverParameters->Pipe->CreatePress(0.0);
MoverParameters->PipePress = 0.0;
MoverParameters->Pipe2->CreatePress(0.0);
MoverParameters->ScndPipePress = 0.0;
MoverParameters->PantVolume = 1;
MoverParameters->PantPress = 0;
MoverParameters->CompressedVolume = 0;
MoverParameters->PantVolume = 0.1;
MoverParameters->PantPress = 0.0;
MoverParameters->CompressedVolume = 0.0;
}
if (ActPar.find('1') != std::string::npos) // wylaczanie 10%
{
if (Random(10) < 1) // losowanie 1/10
{
MoverParameters->BrakeStatus |= 128; // wylacz
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
MoverParameters->Hamulec->ForceEmptiness();
MoverParameters->BrakeReleaser(1); // odluznij automatycznie
}
}
if (ActPar.find('X') != std::string::npos) // agonalny wylaczanie 20%, usrednienie przekladni
{
if (Random(100) < 20) // losowanie 20/100
{
MoverParameters->BrakeStatus |= 128; // wylacz
MoverParameters->Hamulec->SetBrakeStatus( MoverParameters->Hamulec->GetBrakeStatus() | b_dmg ); // wylacz
MoverParameters->Hamulec->ForceEmptiness();
MoverParameters->BrakeReleaser(1); // odluznij automatycznie
}
if (MoverParameters->BrakeCylMult[2] * MoverParameters->BrakeCylMult[1] >
0.01) // jesli jest nastawiacz mechaniczny PL
@@ -1881,8 +1871,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
{ // McZapkie-040602: jeśli coś siedzi w pojeździe
if (Name == Global::asHumanCtrlVehicle) // jeśli pojazd wybrany do prowadzenia
{
if (DebugModeFlag ? false : MoverParameters->EngineType !=
Dumb) // jak nie Debugmode i nie jest dumbem
if ( MoverParameters->EngineType != Dumb)
Controller = Humandriver; // wsadzamy tam sterującego
else // w przeciwnym razie trzeba włączyć pokazywanie kabiny
bDisplayCab = true;
@@ -2443,43 +2432,66 @@ bool TDynamicObject::Update(double dt, double dt1)
if (!bEnabled)
return false; // a normalnie powinny mieć bEnabled==false
// Ra: przeniosłem - no już lepiej tu, niż w wyświetlaniu!
// if ((MoverParameters->ConverterFlag==false) &&
// (MoverParameters->TrainType!=dt_ET22))
// Ra: to nie może tu być, bo wyłącza sprężarkę w rozrządczym EZT!
// if
// ((MoverParameters->ConverterFlag==false)&&(MoverParameters->CompressorPower!=0))
// MoverParameters->CompressorFlag=false;
// if (MoverParameters->CompressorPower==2)
// MoverParameters->CompressorAllow=MoverParameters->ConverterFlag;
// McZapkie-260202
if ((MoverParameters->EnginePowerSource.SourceType == CurrentCollector) &&
(MoverParameters->Power > 1.0)) // aby rozrządczy nie opuszczał silnikowemu
/*
if ((MechInside) || (MoverParameters->TrainType == dt_EZT))
{
*/
// if
// ((!MoverParameters->PantCompFlag)&&(MoverParameters->CompressedVolume>=2.8))
// MoverParameters->PantVolume=MoverParameters->CompressedVolume;
if (MoverParameters->PantPress < (MoverParameters->TrainType == dt_EZT ? 2.4 : 3.5))
{ // 3.5 wg
// http://www.transportszynowy.pl/eu06-07pneumat.php
//"Wyłączniki ciśnieniowe odbieraków prądu wyłączają sterowanie
// wyłącznika szybkiego
// oraz uniemożliwiają podniesienie odbieraków prądu, gdy w instalacji
// rozrządu
// ciśnienie spadnie poniżej wartości 3,5 bara."
// Ra 2013-12: Niebugocław mówi, że w EZT podnoszą się przy 2.5
// if (!MoverParameters->PantCompFlag)
// MoverParameters->PantVolume=MoverParameters->CompressedVolume;
MoverParameters->PantFront(false); // opuszczenie pantografów przy niskim ciśnieniu
MoverParameters->PantRear(false); // to idzie w ukrotnieniu, a nie powinno...
}
// Winger - automatyczne wylaczanie malej sprezarki
else if (MoverParameters->PantPress >= 4.8)
MoverParameters->PantCompFlag = false;
} // Ra: do Mover to trzeba przenieść, żeby AI też mogło sobie podpompować
if( MoverParameters->PantPress < MoverParameters->EnginePowerSource.CollectorParameters.MinPress ) {
// 3.5 wg http://www.transportszynowy.pl/eu06-07pneumat.php
if( true == MoverParameters->PantPressSwitchActive ) {
// 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 ? 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 ? range::unit : range::local ) );
}
}
else {
// specialized variant for EMU -- pwr system disables converter and heating,
// 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, range::unit );
}
// mark the pressure switch as spent
MoverParameters->PantPressSwitchActive = false;
}
}
else {
if( MoverParameters->PantPress >= 4.6 ) {
// NOTE: we require active low power source to prime the pressure switch
// this is a work-around for potential isssues caused by the switch activating on otherwise idle vehicles, but should check whether it's accurate
if( ( true == MoverParameters->Battery )
|| ( true == MoverParameters->ConverterFlag ) ) {
// prime the pressure switch
MoverParameters->PantPressSwitchActive = true;
// turn off the subsystems lock
MoverParameters->PantPressLockActive = false;
}
if( MoverParameters->PantPress >= 4.8 ) {
// Winger - automatyczne wylaczanie malej sprezarki
// TODO: governor lock, disables usage until pressure drop below 3.8 (should really make compressor object we could reuse)
MoverParameters->PantCompFlag = false;
}
}
}
/*
} // Ra: do Mover to trzeba przenieść, żeby AI też mogło sobie podpompować
*/
double dDOMoveLen;
TLocation l;
@@ -2911,37 +2923,29 @@ bool TDynamicObject::Update(double dt, double dt1)
// fragment "z EXE Kursa"
if (MoverParameters->Mains) // nie wchodzić w funkcję bez potrzeby
if ( ( false == MoverParameters->Battery)
if ( ( false == MoverParameters->Battery )
&& ( false == MoverParameters->ConverterFlag ) // added alternative power source. TODO: more generic power check
&& ( Controller == Humandriver)
/*
// NOTE: disabled on account of multi-unit setups, where the unmanned unit wouldn't be affected
&& ( Controller == Humandriver )
*/
&& ( MoverParameters->EngineType != DieselEngine )
&& ( MoverParameters->EngineType != WheelsDriven ) )
{ // jeśli bateria wyłączona, a nie diesel ani drezyna reczna
if (MoverParameters->MainSwitch(false)) // wyłączyć zasilanie
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;
// drop pantographs
// NOTE: this isn't universal behaviour
// 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 ? range::unit : range::local ) );
MoverParameters->PantRear( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) );
*/
}
}
if (MoverParameters->TrainType == dt_ET42)
{ // powinny być wszystkie dwuczłony oraz EZT
/*
//Ra: to jest bez sensu, bo wyłącza WS przy przechodzeniu przez
"wewnętrzne" kabiny (z
powodu ActiveCab)
//trzeba to zrobić inaczej, np. dla członu A sprawdzać, czy jest B
//albo sprawdzać w momencie załączania WS i zmiany w sprzęgach
if
(((TestFlag(MoverParameters->Couplers[1].CouplingFlag,ctrain_controll))&&(MoverParameters->ActiveCab>0)&&(NextConnected->MoverParameters->TrainType!=dt_ET42))||((TestFlag(MoverParameters->Couplers[0].CouplingFlag,ctrain_controll))&&(MoverParameters->ActiveCab<0)&&(PrevConnected->MoverParameters->TrainType!=dt_ET42)))
{//sprawdzenie, czy z tyłu kabiny mamy drugi człon
if (MoverParameters->MainSwitch(false))
MoverParameters->EventFlag=true;
}
if
((!(TestFlag(MoverParameters->Couplers[1].CouplingFlag,ctrain_controll))&&(MoverParameters->ActiveCab>0))||(!(TestFlag(MoverParameters->Couplers[0].CouplingFlag,ctrain_controll))&&(MoverParameters->ActiveCab<0)))
{
if (MoverParameters->MainSwitch(false))
MoverParameters->EventFlag=true;
}
*/
}
// McZapkie-260202 - dMoveLen przyda sie przy stukocie kol
dDOMoveLen =
@@ -3210,21 +3214,27 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->PantRearVolt = 0.0;
break;
} // pozostałe na razie nie obsługiwane
if (MoverParameters->PantPress >
(MoverParameters->TrainType == dt_EZT ? 2.5 : 3.3)) // Ra 2013-12:
// Niebugocław
// mówi, że w EZT
// podnoszą się
// przy 2.5
pantspeedfactor = 0.015 * (MoverParameters->PantPress) *
dt1; // z EXE Kursa //Ra: wysokość zależy od ciśnienia !!!
else
if( MoverParameters->PantPress > (
MoverParameters->TrainType == dt_EZT ?
2.45 : // Ra 2013-12: Niebugocław mówi, że w EZT podnoszą się przy 2.5
3.45 ) ) {
// z EXE Kursa
// Ra: wysokość zależy od ciśnienia !!!
pantspeedfactor = 0.015 * ( MoverParameters->PantPress ) * dt1;
}
else {
pantspeedfactor = 0.0;
if (pantspeedfactor < 0)
pantspeedfactor = 0;
}
if( ( false == MoverParameters->Battery )
&& ( false == MoverParameters->ConverterFlag ) ) {
pantspeedfactor = 0.0;
}
pantspeedfactor = std::max( 0.0, pantspeedfactor );
k = p->fAngleL;
if (i ? MoverParameters->PantRearUp :
MoverParameters->PantFrontUp) // jeśli ma być podniesiony
if( ( pantspeedfactor > 0.0 )
&& ( i ?
MoverParameters->PantRearUp :
MoverParameters->PantFrontUp ) )// jeśli ma być podniesiony
{
if (PantDiff > 0.001) // jeśli nie dolega do drutu
{ // jeśli poprzednia wysokość jest mniejsza niż pożądana, zwiększyć kąt
@@ -3283,6 +3293,9 @@ bool TDynamicObject::Update(double dt, double dt1)
sPantDown.Play(vol, 0, MechInside, vPosition);
MoverParameters->PantRearSP = true;
}
/*
// NOTE: disabled because it's both redundant and doesn't take into account alternative power sources
// converter and compressor will (should) turn off during their individual checks, in the mover's (fast)computemovement() calls
if (MoverParameters->EnginePowerSource.SourceType == CurrentCollector)
{ // Winger 240404 - wylaczanie sprezarki i
// przetwornicy przy braku napiecia
@@ -3292,6 +3305,7 @@ bool TDynamicObject::Update(double dt, double dt1)
MoverParameters->CompressorFlag = false; // Ra: to jest wątpliwe - wyłączenie sprężarki powinno być w jednym miejscu!
}
}
*/
}
else if (MoverParameters->EnginePowerSource.SourceType == InternalSource)
if (MoverParameters->EnginePowerSource.PowerType == SteamPower)
@@ -3546,262 +3560,6 @@ void TDynamicObject::TurnOff()
btMechanik1.TurnOff();
btMechanik2.TurnOff();
};
#ifdef EU07_USE_OLD_RENDERCODE
void TDynamicObject::Render()
{ // rysowanie elementów nieprzezroczystych
// youBy - sprawdzamy, czy jest sens renderowac
if (GfxRenderer.Visible(this))
{
TSubModel::iInstance = (size_t)this; //żeby nie robić cudzych animacji
// AnsiString asLoadName="";
double ObjSqrDist = SquareMagnitude(Global::pCameraPosition - vPosition) / Global::ZoomFactor;
ABuLittleUpdate(ObjSqrDist); // ustawianie zmiennych submodeli dla wspólnego modelu
// Cone(vCoulpler[0],modelRot.z,0);
// Cone(vCoulpler[1],modelRot.z,1);
// ActualTrack= GetTrack(); //McZapkie-240702
#if RENDER_CONE
{ // Ra: testowe renderowanie pozycji wózków w postaci ostrosłupów, wymaga
// GLUT32.DLL
double dir = RadToDeg(atan2(vLeft.z, vLeft.x));
Axle0.Render(0);
Axle1.Render(1); // bogieRot[0]
// if (PrevConnected) //renderowanie połączenia
}
#endif
glPushMatrix();
// vector3 pos= vPosition;
// double ObjDist= SquareMagnitude(Global::pCameraPosition-pos);
if (this == Global::pUserDynamic)
{ // specjalne ustawienie, aby nie trzęsło
#ifdef EU07_USE_OLD_LIGHTING_MODEL
if (Global::bSmudge)
{ // jak jest widoczna smuga, to pojazd renderować po
// wyrenderowaniu smugi
glPopMatrix(); // a to trzeba zebrać przed wyjściem
return;
}
#endif
// if (Global::pWorld->) //tu trzeba by ustawić animacje na modelu
// zewnętrznym
glLoadIdentity(); // zacząć od macierzy jedynkowej
Global::pCamera->SetCabMatrix(vPosition); // specjalne ustawienie kamery
}
else
glTranslated(vPosition.x, vPosition.y,
vPosition.z); // standardowe przesunięcie względem początku scenerii
glMultMatrixd(mMatrix.getArray());
#ifdef EU07_USE_OLD_LIGHTING_MODEL
if (fShade > 0.0)
{ // Ra: zmiana oswietlenia w tunelu, wykopie
GLfloat ambientLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat diffuseLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat specularLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
// trochę problem z ambientem w wykopie...
for (int li = 0; li < 3; li++)
{
ambientLight[li] = Global::ambientDayLight[li] * fShade;
diffuseLight[li] = Global::diffuseDayLight[li] * fShade;
specularLight[li] = Global::specularDayLight[li] * fShade;
}
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
}
#else
if( fShade > 0.0f ) {
// change light level based on light level of the occupied track
Global::DayLight.apply_intensity( fShade );
}
#endif
if (Global::bUseVBO)
{ // wersja VBO
if (mdLowPolyInt)
if (FreeFlyModeFlag ? true : !mdKabina || !bDisplayCab)
mdLowPolyInt->RaRender(ObjSqrDist, ReplacableSkinID, iAlpha);
mdModel->RaRender(ObjSqrDist, ReplacableSkinID, iAlpha);
if (mdLoad) // renderowanie nieprzezroczystego ładunku
mdLoad->RaRender(ObjSqrDist, ReplacableSkinID, iAlpha);
}
else
{ // wersja Display Lists
if( mdLowPolyInt ) {
// low poly interior
if( FreeFlyModeFlag ? true : !mdKabina || !bDisplayCab ) {
// enable cab light if needed
if( InteriorLightLevel > 0.0f ) {
// crude way to light the cabin, until we have something more complete in place
auto const cablight = InteriorLight * InteriorLightLevel;
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &cablight.x );
}
mdLowPolyInt->Render( ObjSqrDist, ReplacableSkinID, iAlpha );
if( InteriorLightLevel > 0.0f ) {
// reset the overall ambient
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
}
}
}
mdModel->Render(ObjSqrDist, ReplacableSkinID, iAlpha);
if (mdLoad) // renderowanie nieprzezroczystego ładunku
mdLoad->Render(ObjSqrDist, ReplacableSkinID, iAlpha);
}
// Ra: czy ta kabina tu ma sens?
// Ra: czy nie renderuje się dwukrotnie?
// Ra: dlaczego jest zablokowana w przezroczystych?
if (mdKabina) // jeśli ma model kabiny
if ((mdKabina != mdModel) && bDisplayCab && FreeFlyModeFlag)
{ // rendering kabiny gdy jest oddzielnym modelem i
// ma byc wyswietlana
// ABu: tylko w trybie FreeFly, zwykly tryb w world.cpp
// Ra: świetła są ustawione dla zewnętrza danego pojazdu
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-mplement this
// oswietlenie kabiny
GLfloat ambientCabLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat diffuseCabLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat specularCabLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
for (int li = 0; li < 3; li++)
{
ambientCabLight[li] = Global::ambientDayLight[li] * 0.9;
diffuseCabLight[li] = Global::diffuseDayLight[li] * 0.5;
specularCabLight[li] = Global::specularDayLight[li] * 0.5;
}
switch (MyTrack->eEnvironment)
{
case e_canyon:
{
for (int li = 0; li < 3; li++)
{
diffuseCabLight[li] *= 0.6f;
specularCabLight[li] *= 0.7f;
}
}
break;
case e_tunnel:
{
for (int li = 0; li < 3; li++)
{
ambientCabLight[li] *= 0.3f;
diffuseCabLight[li] *= 0.1f;
specularCabLight[li] *= 0.2f;
}
}
break;
}
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientCabLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseCabLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularCabLight);
#endif
if (Global::bUseVBO)
mdKabina->RaRender(ObjSqrDist, 0);
else
mdKabina->Render(ObjSqrDist, 0);
#ifdef EU07_USE_OLD_LIGHTING_MODEL
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
#endif
}
#ifdef EU07_USE_OLD_LIGHTING_MODEL
if( fShade != 0.0 ) // tylko jeśli było zmieniane
{ // przywrócenie standardowego oświetlenia
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
}
#else
if( fShade > 0.0f ) {
// restore regular light level
Global::DayLight.apply_intensity();
}
#endif
glPopMatrix();
if (btnOn)
TurnOff(); // przywrócenie domyślnych pozycji submodeli
} // yB - koniec mieszania z grafika
};
void TDynamicObject::RenderAlpha()
{ // rysowanie elementów półprzezroczystych
if (renderme)
{
TSubModel::iInstance = (size_t)this; //żeby nie robić cudzych animacji
double ObjSqrDist = SquareMagnitude(Global::pCameraPosition - vPosition);
ABuLittleUpdate(ObjSqrDist); // ustawianie zmiennych submodeli dla wspólnego modelu
glPushMatrix();
if (this == Global::pUserDynamic)
{ // specjalne ustawienie, aby nie trzęsło
glPopMatrix(); // to trzeba zebrać przed wyściem
return;
glLoadIdentity(); // zacząć od macierzy jedynkowej
Global::pCamera->SetCabMatrix(vPosition); // specjalne ustawienie kamery
}
else
glTranslated(vPosition.x, vPosition.y,
vPosition.z); // standardowe przesunięcie względem początku scenerii
glMultMatrixd(mMatrix.getArray());
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
if (fShade > 0.0)
{ // Ra: zmiana oswietlenia w tunelu, wykopie
GLfloat ambientLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat diffuseLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat specularLight[4] = {0.5f, 0.5f, 0.5f, 1.0f};
// trochę problem z ambientem w wykopie...
for (int li = 0; li < 3; li++)
{
ambientLight[li] = Global::ambientDayLight[li] * fShade;
diffuseLight[li] = Global::diffuseDayLight[li] * fShade;
specularLight[li] = Global::specularDayLight[li] * fShade;
}
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
}
#endif
if (Global::bUseVBO)
{ // wersja VBO
if (mdLowPolyInt)
if (FreeFlyModeFlag ? true : !mdKabina || !bDisplayCab)
mdLowPolyInt->RaRenderAlpha(ObjSqrDist, ReplacableSkinID, iAlpha);
mdModel->RaRenderAlpha(ObjSqrDist, ReplacableSkinID, iAlpha);
if (mdLoad)
mdLoad->RaRenderAlpha(ObjSqrDist, ReplacableSkinID, iAlpha);
}
else
{ // wersja Display Lists
if (mdLowPolyInt)
if (FreeFlyModeFlag ? true : !mdKabina || !bDisplayCab)
mdLowPolyInt->RenderAlpha(ObjSqrDist, ReplacableSkinID, iAlpha);
mdModel->RenderAlpha(ObjSqrDist, ReplacableSkinID, iAlpha);
if (mdLoad)
mdLoad->RenderAlpha(ObjSqrDist, ReplacableSkinID, iAlpha);
}
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
if (fShade != 0.0) // tylko jeśli było zmieniane
{ // przywrócenie standardowego oświetlenia
glLightfv(GL_LIGHT0, GL_AMBIENT, Global::ambientDayLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Global::diffuseDayLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, Global::specularDayLight);
}
#endif
glPopMatrix();
if (btnOn)
TurnOff(); // przywrócenie domyślnych pozycji submodeli
}
return;
} // koniec renderalpha
#endif
void TDynamicObject::RenderSounds()
{ // przeliczanie dźwięków, bo będzie słychać bez wyświetlania sektora z pojazdem
@@ -4124,22 +3882,20 @@ void TDynamicObject::RenderSounds()
sConverter.TurnOff(MechInside, GetPosition());
sConverter.Update(MechInside, GetPosition());
}
if (MoverParameters->WarningSignal > 0)
{
if (TestFlag(MoverParameters->WarningSignal, 1))
sHorn1.TurnOn(MechInside, GetPosition());
else
sHorn1.TurnOff(MechInside, GetPosition());
if (TestFlag(MoverParameters->WarningSignal, 2))
sHorn2.TurnOn(MechInside, GetPosition());
else
sHorn2.TurnOff(MechInside, GetPosition());
if( TestFlag( MoverParameters->WarningSignal, 1 ) ) {
sHorn1.TurnOn( MechInside, GetPosition() );
}
else
{
sHorn1.TurnOff(MechInside, GetPosition());
sHorn2.TurnOff(MechInside, GetPosition());
else {
sHorn1.TurnOff( MechInside, GetPosition() );
}
if( TestFlag( MoverParameters->WarningSignal, 2 ) ) {
sHorn2.TurnOn( MechInside, GetPosition() );
}
else {
sHorn2.TurnOff( MechInside, GetPosition() );
}
if (MoverParameters->DoorClosureWarning)
{
if (MoverParameters->DepartureSignal) // NBMX sygnal odjazdu, MC: pod warunkiem ze jest
@@ -4195,26 +3951,6 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
if( token == "models:") {
// modele i podmodele
#ifdef EU07_USE_OLD_RENDERCODE
iMultiTex = 0; // czy jest wiele tekstur wymiennych?
parser.getTokens();
parser >> asModel;
if( asModel[asModel.size() - 1] == '#' ) // Ra 2015-01: nie podoba mi siê to
{ // model wymaga wielu tekstur wymiennych
iMultiTex = 1;
asModel.erase( asModel.length() - 1 );
}
std::size_t i = asModel.find( ',' );
if ( i != std::string::npos )
{ // Ra 2015-01: może szukać przecinka w nazwie modelu, a po przecinku była by liczba tekstur?
if (i < asModel.length())
iMultiTex = asModel[i + 1] - '0';
if (iMultiTex < 0)
iMultiTex = 0;
else if (iMultiTex > 1)
iMultiTex = 1; // na razie ustawiamy na 1
}
#else
m_materialdata.multi_textures = 0; // czy jest wiele tekstur wymiennych?
parser.getTokens();
parser >> asModel;
@@ -4230,71 +3966,13 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
m_materialdata.multi_textures = asModel[i + 1] - '0';
m_materialdata.multi_textures = clamp( m_materialdata.multi_textures, 0, 1 ); // na razie ustawiamy na 1
}
#endif
asModel = BaseDir + asModel; // McZapkie 2002-07-20: dynamics maja swoje
// modele w dynamics/basedir
Global::asCurrentTexturePath = BaseDir; // biezaca sciezka do tekstur to dynamic/...
mdModel = TModelsManager::GetModel(asModel, true);
assert( mdModel != nullptr ); // TODO: handle this more gracefully than all going to shit
if (ReplacableSkin != "none")
#ifdef EU07_USE_OLD_RENDERCODE
{ // tekstura wymienna jest raczej jedynie w "dynamic\"
ReplacableSkin =
Global::asCurrentTexturePath + ReplacableSkin; // skory tez z dynamic/...
std::string x = TextureTest(Global::asCurrentTexturePath + "nowhere"); // na razie prymitywnie
if (!x.empty())
ReplacableSkinID[4] = GfxRenderer.GetTextureId( Global::asCurrentTexturePath + "nowhere", "", 9);
if (iMultiTex > 0)
{ // jeśli model ma 4 tekstury
ReplacableSkinID[1] = GfxRenderer.GetTextureId(
ReplacableSkin + ",1", "", Global::iDynamicFiltering);
if (ReplacableSkinID[1])
{ // pierwsza z zestawu znaleziona
ReplacableSkinID[2] = GfxRenderer.GetTextureId(
ReplacableSkin + ",2", "", Global::iDynamicFiltering);
if (ReplacableSkinID[2])
{
iMultiTex = 2; // już są dwie
ReplacableSkinID[3] = GfxRenderer.GetTextureId(
ReplacableSkin + ",3", "", Global::iDynamicFiltering);
if (ReplacableSkinID[3])
{
iMultiTex = 3; // a teraz nawet trzy
ReplacableSkinID[4] = GfxRenderer.GetTextureId(
ReplacableSkin + ",4", "", Global::iDynamicFiltering);
if (ReplacableSkinID[4])
iMultiTex = 4; // jak są cztery, to blokujemy podmianę tekstury rozkładem
}
}
}
else
{ // zestaw nie zadziałał, próbujemy normanie
iMultiTex = 0;
ReplacableSkinID[1] = GfxRenderer.GetTextureId(
ReplacableSkin, "", Global::iDynamicFiltering);
}
}
else
ReplacableSkinID[1] = GfxRenderer.GetTextureId(
ReplacableSkin, "", Global::iDynamicFiltering);
if (GfxRenderer.Texture(ReplacableSkinID[1]).has_alpha)
iAlpha = 0x31310031; // tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
else
iAlpha = 0x30300030; // wszystkie tekstury nieprzezroczyste - nie renderować w cyklu przezroczystych
if (ReplacableSkinID[2])
if (GfxRenderer.Texture(ReplacableSkinID[2]).has_alpha)
iAlpha |= 0x02020002; // tekstura -2 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
if (ReplacableSkinID[3])
if (GfxRenderer.Texture(ReplacableSkinID[3]).has_alpha)
iAlpha |= 0x04040004; // tekstura -3 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
if (ReplacableSkinID[4])
if (GfxRenderer.Texture(ReplacableSkinID[4]).has_alpha)
iAlpha |= 0x08080008; // tekstura -4 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
}
#else
{ // tekstura wymienna jest raczej jedynie w "dynamic\"
// ReplacableSkin = Global::asCurrentTexturePath + ReplacableSkin; // skory tez z dynamic/...
{
std::string nowheretexture = TextureTest(Global::asCurrentTexturePath + "nowhere"); // na razie prymitywnie
if( false == nowheretexture.empty() ) {
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.GetTextureId( nowheretexture, "", 9 );
@@ -4349,7 +4027,6 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
if( GfxRenderer.Texture( m_materialdata.replacable_skins[ 4 ] ).has_alpha )
m_materialdata.textures_alpha |= 0x08080008; // tekstura -4 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
}
#endif
if (!MoverParameters->LoadAccepted.empty())
// if (MoverParameters->LoadAccepted!=AnsiString("")); // &&
// MoverParameters->LoadType!=AnsiString("passengers"))
@@ -5056,7 +4733,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
// plik z przyspieszaczem (upust po zlapaniu hamowania)
// sBrakeAcc.Init(str.c_str(),Parser->GetNextSymbol().ToDouble(),GetPosition().x,GetPosition().y,GetPosition().z,true);
parser.getTokens( 1, false ); parser >> token;
sBrakeAcc = TSoundsManager::GetFromName( token.c_str(), true );
sBrakeAcc = TSoundsManager::GetFromName( token, true );
bBrakeAcc = true;
// sBrakeAcc.AM=1.0;
// sBrakeAcc.AA=0.0;
@@ -5271,10 +4948,19 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
//---------------------------------------------------------------------------
void TDynamicObject::RadioStop()
{ // zatrzymanie pojazdu
if (Mechanik) // o ile ktoś go prowadzi
if (MoverParameters->SecuritySystem.RadioStop &&
MoverParameters->Radio) // jeśli pojazd ma RadioStop i jest on aktywny
Mechanik->PutCommand("Emergency_brake", 1.0, 1.0, &vPosition, stopRadio);
if( Mechanik ) {
// o ile ktoś go prowadzi
if( ( MoverParameters->SecuritySystem.RadioStop )
&& ( MoverParameters->Radio ) ) {
// jeśli pojazd ma RadioStop i jest on aktywny
Mechanik->PutCommand( "Emergency_brake", 1.0, 1.0, &vPosition, stopRadio );
// add onscreen notification for human driver
// TODO: do it selectively for the 'local' driver once the multiplayer is in
if( false == Mechanik->AIControllFlag ) {
Global::tranTexts.AddLine( "!! RADIO-STOP !!", 0.0, 10.0, false );
}
}
}
};
//---------------------------------------------------------------------------
@@ -5552,22 +5238,27 @@ TDynamicObject * TDynamicObject::ControlledFind()
// jeździć dobrze
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
TDynamicObject *d = this; // zaczynamy od aktualnego
if (d->MoverParameters->TrainType & dt_EZT) // na razie dotyczy to EZT
if (d->NextConnected ? d->MoverParameters->Couplers[1].AllowedFlag & ctrain_depot : false)
{ // gdy jest człon od sprzęgu 1, a sprzęg łączony
// warsztatowo (powiedzmy)
if ((d->MoverParameters->Power < 1.0) && (d->NextConnected->MoverParameters->Power >
1.0)) // my nie mamy mocy, ale ten drugi ma
if( d->MoverParameters->TrainType & dt_EZT ) {
// na razie dotyczy to EZT
if( ( d->NextConnected != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ 1 ].AllowedFlag, coupling::permanent ) ) ) {
// gdy jest człon od sprzęgu 1, a sprzęg łączony warsztatowo (powiedzmy)
if( ( d->MoverParameters->Power < 1.0 )
&& ( d->NextConnected->MoverParameters->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
d = d->NextConnected; // będziemy sterować tym z mocą
}
}
else if (d->PrevConnected ? d->MoverParameters->Couplers[0].AllowedFlag & ctrain_depot :
false)
{ // gdy jest człon od sprzęgu 0, a sprzęg łączony
// warsztatowo (powiedzmy)
if ((d->MoverParameters->Power < 1.0) && (d->PrevConnected->MoverParameters->Power >
1.0)) // my nie mamy mocy, ale ten drugi ma
else if( ( d->PrevConnected != nullptr )
&& ( true == TestFlag( d->MoverParameters->Couplers[ 0 ].AllowedFlag, coupling::permanent ) ) ) {
// gdy jest człon od sprzęgu 0, a sprzęg łączony warsztatowo (powiedzmy)
if( ( d->MoverParameters->Power < 1.0 )
&& ( d->PrevConnected->MoverParameters->Power > 1.0 ) ) {
// my nie mamy mocy, ale ten drugi ma
d = d->PrevConnected; // będziemy sterować tym z mocą
}
}
}
return d;
};
//---------------------------------------------------------------------------
@@ -5631,62 +5322,16 @@ std::string TDynamicObject::TextureTest(std::string const &name)
return ""; // nie znaleziona
};
#ifdef EU07_USE_OLD_RENDERCODE
void TDynamicObject::DestinationSet(std::string to, std::string numer)
{ // ustawienie stacji
// docelowej oraz wymiennej
// tekstury 4, jeśli
// istnieje plik
// w zasadzie, to każdy wagon mógłby mieć inną stację docelową
// zwłaszcza w towarowych, pod kątem zautomatyzowania maewrów albo pracy górki
// ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z
// rozkładu
if (abs(iMultiTex) >= 4)
return; // jak są 4 tekstury wymienne, to nie zmieniać rozkładem
numer = Global::Bezogonkow(numer);
asDestination = to;
to = Global::Bezogonkow(to); // do szukania pliku obcinamy ogonki
std::string x = TextureTest(asBaseDir + numer + "@" + MoverParameters->TypeName);
if (!x.empty())
{
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
return;
}
x = TextureTest(asBaseDir + numer );
if (!x.empty())
{
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
return;
}
if (to.empty())
to = "nowhere";
x = TextureTest(asBaseDir + to + "@" + MoverParameters->TypeName); // w pierwszej kolejności z nazwą FIZ/MMD
if (!x.empty())
{
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
return;
}
x = TextureTest(asBaseDir + to); // na razie prymitywnie
if (!x.empty())
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9); // rozmywania 0,1,4,5 nie nadają się
else
{
x = TextureTest(asBaseDir + "nowhere"); // jak nie znalazł dedykowanej, to niech daje nowhere
if (!x.empty())
ReplacableSkinID[4] = GfxRenderer.GetTextureId( x, "", 9);
}
// Ra 2015-01: żeby zalogować błąd, trzeba by mieć pewność, że model używa
// tekstury nr 4
};
#else
void TDynamicObject::DestinationSet(std::string to, std::string numer)
{ // ustawienie stacji docelowej oraz wymiennej tekstury 4, jeśli istnieje plik
// w zasadzie, to każdy wagon mógłby mieć inną stację docelową
// zwłaszcza w towarowych, pod kątem zautomatyzowania maewrów albo pracy górki
// ale to jeszcze potrwa, zanim będzie możliwe, na razie można wpisać stację z
// rozkładu
if( std::abs( m_materialdata.multi_textures ) >= 4 )
return; // jak są 4 tekstury wymienne, to nie zmieniać rozkładem
if( std::abs( m_materialdata.multi_textures ) >= 4 ) {
// jak są 4 tekstury wymienne, to nie zmieniać rozkładem
return;
}
numer = Global::Bezogonkow(numer);
asDestination = to;
to = Global::Bezogonkow(to); // do szukania pliku obcinamy ogonki
@@ -5719,10 +5364,8 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer)
if (!x.empty())
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.GetTextureId( x, "", 9 );
}
// Ra 2015-01: żeby zalogować błąd, trzeba by mieć pewność, że model używa
// tekstury nr 4
// Ra 2015-01: żeby zalogować błąd, trzeba by mieć pewność, że model używa tekstury nr 4
};
#endif
void TDynamicObject::OverheadTrack(float o)
{ // ewentualne wymuszanie jazdy

View File

@@ -137,11 +137,8 @@ class TAnim
void Parovoz(); // wykonanie obliczeń animacji
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#ifndef EU07_USE_OLD_RENDERCODE
// parameters for the material object, as currently used by various simulator models
struct material_data {
@@ -153,7 +150,6 @@ struct material_data {
::SecureZeroMemory( replacable_skins, sizeof( replacable_skins ) );
}
};
#endif
class TDynamicObject { // klasa pojazdu
@@ -200,15 +196,11 @@ public: // modele składowe pojazdu
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
#ifndef EU07_USE_OLD_RENDERCODE
material_data m_materialdata;
#endif
public:
#ifndef EU07_USE_OLD_RENDERCODE
inline
material_data const *Material() const { return &m_materialdata; }
#endif
material_data const *Material() const { return &m_materialdata; }
// tymczasowo udostępnione do wyszukiwania drutu
int iAnimType[ ANIM_TYPES ]; // 0-osie,1-drzwi,2-obracane,3-zderzaki,4-wózki,5-pantografy,6-tłoki
private:
@@ -421,11 +413,6 @@ public: // modele składowe pojazdu
int iCabs; // maski bitowe modeli kabin
TTrack *MyTrack; // McZapkie-030303: tor na ktorym stoi, ABu
std::string asBaseDir;
#ifdef EU07_USE_OLD_RENDERCODE
texture_manager::size_type ReplacableSkinID[5]; // McZapkie:zmienialne nadwozie
int iAlpha; // maska przezroczystości tekstur
int iMultiTex; //<0 tekstury wskazane wpisem, >0 tekstury z przecinkami, =0 jedna
#endif
int iOverheadMask; // maska przydzielana przez AI pojazdom posiadającym pantograf, aby wymuszały
// jazdę bezprądową
TTractionParam tmpTraction;
@@ -444,10 +431,6 @@ public: // modele składowe pojazdu
bool FastUpdate(double dt);
void Move(double fDistance);
void FastMove(double fDistance);
#ifdef EU07_USE_OLD_RENDERCODE
void Render();
void RenderAlpha();
#endif
void RenderSounds();
inline vector3 GetPosition() const
{
@@ -546,6 +529,7 @@ public: // modele składowe pojazdu
std::string TextureTest(std::string const &name);
void OverheadTrack(float o);
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
static std::string const MED_labels[ 8 ];
};
//---------------------------------------------------------------------------

View File

@@ -9,7 +9,6 @@ http://mozilla.org/MPL/2.0/.
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
*/
/*
Authors:
@@ -40,6 +39,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
#pragma comment (lib, "winmm.lib")
#pragma comment (lib, "setupapi.lib")
#pragma comment (lib, "dbghelp.lib")
#pragma comment (lib, "version.lib")
TWorld World;
@@ -195,7 +195,9 @@ int main(int argc, char *argv[])
SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), FOREGROUND_GREEN );
}
for (int i = 1; i < argc; i++)
Global::asVersion = "NG";
for (int i = 1; i < argc; ++i)
{
std::string token(argv[i]);
@@ -297,20 +299,17 @@ int main(int argc, char *argv[])
#endif
Global::pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów
try
{
if ((false == GfxRenderer.Init(window))
|| (false == UILayer.init(window)))
return -1;
input::Keyboard.init();
input::Gamepad.init();
try {
if( false == World.Init( window ) ) {
ErrorLog( "Failed to init TWorld" );
return -1;
}
}
catch( std::bad_alloc const &Error ) {
if (!World.Init(window))
{
std::cout << "failed to init TWorld" << std::endl;
return -1;
}
}
ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) );
return -1;
}
catch (std::runtime_error e)
{
WriteLog(e.what());
@@ -334,13 +333,23 @@ int main(int argc, char *argv[])
} // po zrobieniu E3D odpalamy normalnie scenerię, by ją zobaczyć
Console::On(); // włączenie konsoli
while (!glfwWindowShouldClose(window)
&& World.Update()
&& GfxRenderer.Render())
{
glfwPollEvents();
input::Gamepad.poll();
try {
while( ( false == glfwWindowShouldClose( window ) )
&& ( true == World.Update() )
&& ( true == GfxRenderer.Render() ) ) {
glfwPollEvents();
if( true == Global::InputGamepad ) {
input::Gamepad.poll();
}
}
}
catch( std::bad_alloc const &Error ) {
ErrorLog( "Critical error, memory allocation failure: " + std::string( Error.what() ) );
return -1;
}
Console::Off(); // wyłączenie konsoli (komunikacji zwrotnej)
}

View File

@@ -610,14 +610,32 @@ void TEvent::Load(cParser *parser, vector3 *org)
}
};
void TEvent::AddToQuery(TEvent *e)
{ // dodanie eventu do kolejki
if (evNext ? (e->fStartTime >= evNext->fStartTime) : false)
evNext->AddToQuery(e); // sortowanie wg czasu
else
{ // dodanie z przodu
e->evNext = evNext;
evNext = e;
void TEvent::AddToQuery( TEvent *Event, TEvent *&Start ) {
TEvent *target( Start );
TEvent *previous( nullptr );
while( ( Event->fStartTime >= target->fStartTime )
&& ( target->evNext != nullptr ) ) {
previous = target;
target = target->evNext;
}
// the new event will be either before or after the one we located
if( Event->fStartTime >= target->fStartTime ) {
assert( target->evNext == nullptr );
target->evNext = Event;
// if we have resurrected event land at the end of list, the link from previous run could potentially "add" unwanted events to the queue
Event->evNext = nullptr;
}
else {
if( previous != nullptr ) {
previous->evNext = Event;
Event->evNext = target;
}
else {
// special case, we're inserting our event before the provided start point
Event->evNext = Start;
Start = Event;
}
}
}

View File

@@ -105,7 +105,7 @@ class TEvent // zmienne: ev*
~TEvent();
void Init();
void Load(cParser *parser, vector3 *org);
void AddToQuery(TEvent *e);
static void AddToQuery( TEvent *Event, TEvent *&Start );
std::string CommandGet();
TCommandType Command();
double ValueGet(int n);

View File

@@ -25,7 +25,7 @@ void TFadeSound::Free()
{
}
void TFadeSound::Init(char *Name, float fNewFade)
void TFadeSound::Init(std::string const &Name, float fNewFade)
{
Sound = TSoundsManager::GetFromName(Name, false);
if (Sound)

View File

@@ -24,7 +24,7 @@ class TFadeSound
public:
TFadeSound();
~TFadeSound();
void Init(char *Name, float fNewFade);
void Init(std::string const &Name, float fNewFade);
void TurnOn();
void TurnOff();
bool Playing()

View File

@@ -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,8 +47,7 @@ GLFWwindow *Global::window;
bool Global::shiftState;
bool Global::ctrlState;
int Global::iCameraLast = -1;
std::string Global::asRelease = "NG";
std::string Global::asVersion = "EU07++NG";
std::string Global::asVersion = "UNKNOWN";
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
@@ -84,16 +82,7 @@ GLfloat Global::FogColor[] = {0.6f, 0.7f, 0.8f};
double Global::fFogStart = 1700;
double Global::fFogEnd = 2000;
float Global::Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
#ifdef EU07_USE_OLD_LIGHTING_MODEL
GLfloat Global::ambientDayLight[] = {0.40f, 0.40f, 0.45f, 1.0f}; // robocze
GLfloat Global::diffuseDayLight[] = {0.55f, 0.54f, 0.50f, 1.0f};
GLfloat Global::specularDayLight[] = {0.95f, 0.94f, 0.90f, 1.0f};
GLfloat Global::ambientLight[] = {0.80f, 0.80f, 0.85f, 1.0f}; // stałe
GLfloat Global::diffuseLight[] = {0.85f, 0.85f, 0.80f, 1.0f};
GLfloat Global::specularLight[] = {0.95f, 0.94f, 0.90f, 1.0f};
#else
int Global::DynamicLightCount = 7;
#endif
GLfloat Global::whiteLight[] = {1.00f, 1.00f, 1.00f, 1.0f};
GLfloat Global::noLight[] = {0.00f, 0.00f, 0.00f, 1.0f};
GLfloat Global::darkLight[] = {0.03f, 0.03f, 0.03f, 1.0f}; //śladowe
@@ -110,6 +99,7 @@ int Global::iWindowHeight = 600;
float Global::fDistanceFactor = Global::ScreenHeight / 768.0; // baza do przeliczania odległości dla LoD
int Global::iFeedbackMode = 1; // tryb pracy informacji zwrotnej
int Global::iFeedbackPort = 0; // dodatkowy adres dla informacji zwrotnych
bool Global::InputGamepad{ true };
bool Global::bFreeFly = false;
bool Global::bFullScreen = false;
bool Global::VSync{ false };
@@ -796,6 +786,11 @@ void Global::ConfigParse(cParser &Parser)
>> Global::Background[1] // g
>> Global::Background[2]; // b
}
else if( token == "input.gamepad" ) {
// czy grupować eventy o tych samych nazwach
Parser.getTokens();
Parser >> Global::InputGamepad;
}
// maciek001: ustawienia MWD
else if (token == "mwdmasterenable") { // główne włączenie maszyny!
Parser.getTokens();

View File

@@ -130,7 +130,9 @@ class TTranscript
float fHide; // czas ukrycia/usunięcia
std::string asText; // tekst gotowy do wyświetlenia (usunięte znaczniki czasu)
bool bItalic; // czy kursywa (dźwięk nieistotny dla prowadzącego)
/*
int iNext; // następna używana linijka, żeby nie przestawiać fizycznie tabeli
*/
};
/*
@@ -219,19 +221,10 @@ class Global
static GLfloat FogColor[];
static float Overcast;
// static bool bTimeChange;
#ifdef EU07_USE_OLD_LIGHTING_MODEL
static opengl_light AmbientLight;
static GLfloat ambientDayLight[];
static GLfloat diffuseDayLight[];
static GLfloat specularDayLight[];
static GLfloat ambientLight[];
static GLfloat diffuseLight[];
static GLfloat specularLight[];
#else
// TODO: put these things in the renderer
static int DynamicLightCount;
#endif
static GLfloat whiteLight[];
static GLfloat noLight[];
static GLfloat darkLight[];
@@ -251,6 +244,7 @@ class Global
static std::string LastGLError;
static int iFeedbackMode; // tryb pracy informacji zwrotnej
static int iFeedbackPort; // dodatkowy adres dla informacji zwrotnych
static bool InputGamepad; // whether gamepad support is enabled
static double fLuminance; // jasność światła do automatycznego zapalania
static float SunAngle; // angle of the sun relative to horizon
static int iMultiplayer; // blokada działania niektórych eventów na rzecz kominikacji
@@ -262,7 +256,6 @@ 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 GLint iMaxTextureSize; // maksymalny rozmiar tekstury
static int iTextMode; // tryb pracy wyświetlacza tekstowego
@@ -283,7 +276,7 @@ class Global
static bool bGlutFont; // tekst generowany przez GLUT
static int iKeyLast; // ostatnio naciśnięty klawisz w celu logowania
static int iPause; // globalna pauza ruchu: b0=start,b1=klawisz,b2=tło,b3=lagi,b4=wczytywanie
static void BindTexture(GLuint t);
static int iConvertModels; // tworzenie plików binarnych
static int iErorrCounter; // licznik sprawdzań do śledzenia błędów OpenGL
static bool bInactivePause; // automatyczna pauza, gdy okno nieaktywne

1556
Ground.cpp

File diff suppressed because it is too large Load Diff

108
Ground.h
View File

@@ -69,7 +69,7 @@ struct TGroundVertex
{
vector3 Point;
vector3 Normal;
float tu, tv;
float tu{ 0.0f }, tv{ 0.0f };
void HalfSet(const TGroundVertex &v1, const TGroundVertex &v2)
{ // wyliczenie współrzędnych i mapowania punktu na środku odcinka v1<->v2
Point = 0.5 * (v1.Point + v2.Point);
@@ -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
@@ -121,24 +122,20 @@ class TGroundNode : public Resource
TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
};
std::string asName; // nazwa (nie zawsze ma znaczenie)
vector3 pCenter; // współrzędne środka do przydzielenia sektora
vector3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
// visualization-related data
// TODO: wrap these in a struct, when cleaning objects up
union
{
int iNumVerts; // dla trójkątów
int iNumPts; // dla linii
int iCount; // dla terenu
// int iState; //Ra: nie używane - dźwięki zapętlone
};
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
int iVersion; // wersja siatki (do wykonania rekompilacji)
// union ?
GLuint DisplayListID; // numer siatki DisplayLists
@@ -148,6 +145,7 @@ class TGroundNode : public Resource
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
int Ambient[4], Diffuse[4], Specular[4]; // oświetlenie
bool bVisible;
TGroundNode *nNext; // lista wszystkich w scenerii, ostatni na początku
TGroundNode *nNext2; // lista obiektów w sektorze
TGroundNode *nNext3; // lista obiektów renderowanych we wspólnym cyklu
@@ -158,8 +156,6 @@ class TGroundNode : public Resource
void InitCenter(); // obliczenie współrzędnych środka
void InitNormals();
void MoveMe(vector3 pPosition); // przesuwanie (nie działa)
// bool Disable();
inline TGroundNode * Find(const std::string &asNameToFind, TGroundNodeType iNodeType)
{ // wyszukiwanie czołgowe z typem
@@ -170,23 +166,18 @@ class TGroundNode : public Resource
return NULL;
};
void Compile(bool many = false);
void Compile(Math3D::vector3 const &Origin, bool const Multiple = false);
void Release();
bool GetTraction();
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
};
struct bounding_area {
float3 center; // mid point of the rectangle
glm::vec3 center; // mid point of the rectangle
float radius{ 0.0f }; // radius of the bounding sphere
};
@@ -201,16 +192,17 @@ class TSubRect : public Resource, public CMesh
TGroundNode *nRootMesh = nullptr; // obiekty renderujące wg tekstury (wtórne, lista po nNext2)
TGroundNode *nMeshed = nullptr; // lista obiektów dla których istnieją obiekty renderujące grupowo
public:
TGroundNode *
nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2)
TGroundNode *
nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3)
TGroundNode *nRootNode = nullptr; // wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2)
TGroundNode *nRenderHidden = nullptr; // lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3)
TGroundNode *nRenderRect = nullptr; // z poziomu sektora - nieprzezroczyste (nNext3)
TGroundNode *nRenderRectAlpha = nullptr; // z poziomu sektora - przezroczyste (nNext3)
TGroundNode *nRenderWires = nullptr; // z poziomu sektora - druty i inne linie (nNext3)
TGroundNode *nRender = nullptr; // indywidualnie - nieprzezroczyste (nNext3)
TGroundNode *nRenderMixed = nullptr; // indywidualnie - nieprzezroczyste i przezroczyste (nNext3)
TGroundNode *nRenderAlpha = nullptr; // indywidualnie - przezroczyste (nNext3)
#ifdef EU07_SCENERY_EDITOR
std::deque< TGroundNode* > m_memcells; // collection of memcells present in the sector
#endif
int iNodeCount = 0; // licznik obiektów, do pomijania pustych sektorów
public:
void LoadNodes(); // utworzenie VBO sektora
@@ -222,15 +214,9 @@ 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
void RenderAlphaDL(); // renderowanie przezroczystych w Display Lists
// (McZapkie-131202)
void RenderVBO(); // renderowanie nieprzezroczystych z własnego VBO
void RenderAlphaVBO(); // renderowanie przezroczystych z (własnego) VBO
void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów
};
@@ -247,6 +233,8 @@ class TGroundRect : public TSubRect
{ // kwadrat kilometrowy
// obiekty o niewielkiej ilości wierzchołków będą renderowane stąd
// Ra: 2012-02 doszły submodele terenu
friend class opengl_renderer;
private:
int iLastDisplay; // numer klatki w której był ostatnio wyświetlany
TSubRect *pSubRects{ nullptr };
@@ -273,8 +261,6 @@ class TGroundRect : public TSubRect
for (int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i)
pSubRects[i].Sort(); // optymalizacja obiektów w sektorach
};
void RenderDL();
void RenderVBO();
};
class TGround
@@ -288,9 +274,7 @@ class TGround
TGroundRect Rects[iNumRects][iNumRects]; // mapa kwadratów kilometrowych
TEvent *RootEvent = nullptr; // lista zdarzeń
TEvent *QueryRootEvent = nullptr,
*tmpEvent = nullptr,
*tmp2Event = nullptr,
*OldQRE = nullptr;
*tmpEvent = nullptr;
TSubRect *pRendered[1500]; // lista renderowanych sektorów
int iNumNodes = 0;
vector3 pOrigin;
@@ -299,8 +283,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 +295,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 +308,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 +320,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);
@@ -383,16 +334,15 @@ class TGround
{
return &Rects[GetColFromX(x) / iNumSubRects][GetRowFromZ(z) / iNumSubRects];
};
TSubRect * GetSubRect( int iCol, int iRow );
TSubRect * GetSubRect(double x, double z)
{
return GetSubRect(GetColFromX(x), GetRowFromZ(z));
};
TSubRect * FastGetSubRect(double x, double z)
{
return FastGetSubRect(GetColFromX(x), GetRowFromZ(z));
TSubRect * FastGetSubRect( int iCol, int iRow );
TSubRect * FastGetSubRect( double x, double z ) {
return FastGetSubRect( GetColFromX( x ), GetRowFromZ( z ) );
};
TSubRect * GetSubRect(int iCol, int iRow);
TSubRect * FastGetSubRect(int iCol, int iRow);
int GetRowFromZ(double z)
{
return (int)(z / fSubRectSize + fHalfTotalNumSubRects);
@@ -406,7 +356,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 +368,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,

View File

@@ -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;

View File

@@ -139,7 +139,29 @@ 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,
brakehose = 0x2,
control = 0x4,
highvoltage = 0x8,
gangway = 0x10,
mainhose = 0x20,
heating = 0x40,
permanent = 0x80
};
// 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;
static int const dbrake_passive = 1;
@@ -269,7 +291,8 @@ struct TCommand
std::string Command; /*komenda*/
double Value1 = 0.0; /*argumenty komendy*/
double Value2 = 0.0;
TLocation Location;
int Coupling{ ctrain_controll }; // coupler flag used to determine command propagation
TLocation Location;
};
/*tory*/
@@ -360,14 +383,14 @@ struct TBoilerType {
};
/*rodzaj odbieraka pradu*/
struct TCurrentCollector {
long CollectorsNo; //musi być tu, bo inaczej się kopie
double MinH; double MaxH; //zakres ruchu pantografu, nigdzie nie używany
double CSW; //szerokość części roboczej (styku) ślizgacza
double MinV; double MaxV; //minimalne i maksymalne akceptowane napięcie
double OVP; //czy jest przekaznik nadnapieciowy
double InsetV; //minimalne napięcie wymagane do załączenia
double MinPress; //minimalne ciśnienie do załączenia WS
double MaxPress; //maksymalne ciśnienie za reduktorem
long CollectorsNo{ 0 }; //musi być tu, bo inaczej się kopie
double MinH{ 0.0 }; double MaxH{ 0.0 }; //zakres ruchu pantografu, nigdzie nie używany
double CSW{ 0.0 }; //szerokość części roboczej (styku) ślizgacza
double MinV{ 0.0 }; double MaxV{ 0.0 }; //minimalne i maksymalne akceptowane napięcie
double OVP{ 0.0 }; //czy jest przekaznik nadnapieciowy
double InsetV{ 0.0 }; //minimalne napięcie wymagane do załączenia
double MinPress{ 0.0 }; //minimalne ciśnienie do załączenia WS
double MaxPress{ 0.0 }; //maksymalne ciśnienie za reduktorem
//inline TCurrentCollector() {
// CollectorsNo = 0;
// MinH, MaxH, CSW, MinV, MaxV = 0.0;
@@ -536,6 +559,12 @@ struct TTransmision
enum TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic };
struct power_coupling {
double current{ 0.0 };
double voltage{ 0.0 };
bool local{ false }; // whether the power comes from external or onboard source
};
struct TCoupling {
/*parametry*/
double SpringKB = 1.0; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */
@@ -556,6 +585,9 @@ struct TCoupling {
double CForce = 0.0; /*sila z jaka dzialal*/
double Dist = 0.0; /*strzalka ugiecia zderzaków*/
bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/
power_coupling power_high;
power_coupling power_low; // TODO: implement this
};
class TMoverParameters
@@ -747,6 +779,7 @@ public:
double Ftmax = 0.0;
/*- dla lokomotyw z silnikami indukcyjnymi -*/
double eimc[26];
static std::vector<std::string> const eimc_labels;
/*-dla wagonow*/
double MaxLoad = 0.0; /*masa w T lub ilosc w sztukach - ladownosc*/
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
@@ -768,7 +801,17 @@ public:
TRotation Rot;
std::string Name; /*nazwa wlasna*/
TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
double HVCouplers[2][2]; //przewod WN
enum side {
front = 0,
rear
};
#ifdef EU07_USE_OLD_HVCOUPLERS
double HVCouplers[ 2 ][ 2 ]; //przewod WN
enum hvcoupler {
current = 0,
voltage
};
#endif
int ScanCounter = 0; /*pomocnicze do skanowania sprzegow*/
bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/
int SoundFlag = 0; /*!o patrz stale sound_ */
@@ -804,15 +847,25 @@ public:
bool CompressorFlag = false; /*!o czy wlaczona sprezarka*/
bool PantCompFlag = false; /*!o czy wlaczona sprezarka pantografow*/
bool CompressorAllow = false; /*! zezwolenie na uruchomienie sprezarki NBMX*/
bool ConverterFlag = false ; /*! czy wlaczona przetwornica NBMX*/
bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
// 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 ConverterAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
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*/
int ManualBrakePos = 0; /*nastawa hamulca recznego*/
double LocalBrakePosA = 0.0;
int BrakeStatus = b_off; /*0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R*/
/*
int BrakeStatus = b_off; //0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R
*/
bool EmergencyBrakeFlag = false; /*hamowanie nagle*/
int BrakeDelayFlag = 0; /*nastawa opoznienia ham. osob/towar/posp/exp 0/1/2/4*/
int BrakeDelays = 0; /*nastawy mozliwe do uzyskania*/
@@ -886,7 +939,9 @@ public:
double RventRot = 0.0; /*!s obroty wentylatorow rozruchowych*/
bool UnBrake = false; /*w EZT - nacisniete odhamowywanie*/
double PantPress = 0.0; /*Cisnienie w zbiornikach pantografow*/
bool s_CAtestebrake = false; //hunter-091012: zmienna dla testu ca
bool PantPressSwitchActive{ false }; // state of the pantograph pressure switch. gets primed at defined pressure level in pantograph air system
bool PantPressLockActive{ false }; // pwr system state flag. fires when pressure switch activates by pantograph pressure dropping below defined level
bool s_CAtestebrake = false; //hunter-091012: zmienna dla testu ca
/*-zmienne dla lokomotywy spalinowej z przekladnia mechaniczna*/
double dizel_fill = 0.0; /*napelnienie*/
@@ -898,6 +953,7 @@ public:
/*- zmienne dla lokomotyw z silnikami indukcyjnymi -*/
double eimv[21];
static std::vector<std::string> const eimv_labels;
/*-zmienne dla drezyny*/
double PulseForce = 0.0; /*przylozona sila*/
@@ -924,8 +980,10 @@ public:
int PantRearStart = 0;
double PantFrontVolt = 0.0; //pantograf pod napieciem? 'Winger 160404
double PantRearVolt = 0.0;
// TODO: move these switch types where they belong, cabin definition
std::string PantSwitchType;
std::string ConvSwitchType;
std::string StLinSwitchType;
bool Heating = false; //ogrzewanie 'Winger 020304
int DoubleTr = 1; //trakcja ukrotniona - przedni pojazd 'Winger 160304
@@ -982,11 +1040,11 @@ public:
/*! przesylanie komend sterujacych*/
bool SendCtrlBroadcast(std::string CtrlCommand, double ctrlvalue);
bool SendCtrlToNext(std::string CtrlCommand, double ctrlvalue, double dir);
bool SetInternalCommand(std::string NewCommand, double NewValue1, double NewValue2);
bool SendCtrlToNext(std::string const CtrlCommand, double const ctrlvalue, double const dir, int const Couplertype = ctrain_controll);
bool SetInternalCommand( std::string NewCommand, double NewValue1, double NewValue2, int const Couplertype = ctrain_controll );
double GetExternalCommand(std::string &Command);
bool RunCommand(std::string Command, double CValue1, double CValue2);
bool RunInternalCommand(void);
bool RunCommand( std::string Command, double CValue1, double CValue2, int const Couplertype = ctrain_controll );
bool RunInternalCommand();
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation);
bool CabActivisation(void);
bool CabDeactivisation(void);
@@ -1002,7 +1060,7 @@ public:
bool AddPulseForce(int Multipler);/*dla drezyny*/
bool SandDoseOn(void);/*wlacza/wylacza sypanie piasku*/
bool Sandbox( bool const State, int const Notify = range::consist );/*wlacza/wylacza sypanie piasku*/
/*! zbijanie czuwaka/SHP*/
void SSReset(void);
@@ -1058,12 +1116,12 @@ public:
/*--funkcje dla lokomotyw*/
bool DirectionBackward(void);/*! kierunek ruchu*/
bool MainSwitch(bool State);/*! wylacznik glowny*/
bool ConverterSwitch(bool State);/*! wl/wyl przetwornicy*/
bool CompressorSwitch(bool State);/*! 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
@@ -1074,7 +1132,7 @@ public:
/*function ShowEngineRotation(VehN:int): integer; //Ra 2014-06: przeniesione do C++*/
/*funkcje uzalezniajace sile pociagowa od predkosci: v2n, n2r, current, momentum*/
double v2n(void);
double current(double n, double U);
double Current(double n, double U);
double Momentum(double I);
double MomentumF(double I, double Iw, int SCP);
@@ -1086,8 +1144,8 @@ public:
bool AutoRelayCheck(void);//symulacja automatycznego rozruchu
bool ResistorsFlagCheck(void); //sprawdzenie kontrolki oporow rozruchowych NBMX
bool PantFront(bool State); //obsluga pantografou przedniego
bool PantRear(bool State); //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);

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,7 @@ Copyright (C) 2007-2014 Maciej Cierniak
#include "hamulce.h"
#include <typeinfo>
#include "Mover.h"
#include "usefull.h"
//---FUNKCJE OGOLNE---
@@ -51,10 +52,10 @@ double PF_old(double P1, double P2, double S)
double PF( double const P1, double const P2, double const S, double const DP )
{
double PH = std::max(P1, P2) + 1; // wyzsze cisnienie absolutne
double PL = P1 + P2 - PH + 2; // nizsze cisnienie absolutne
double sg = PL / PH; // bezwymiarowy stosunek cisnien
double FM = PH * 197 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem
double const PH = std::max(P1, P2) + 1.0; // wyzsze cisnienie absolutne
double const PL = P1 + P2 - PH + 2.0; // nizsze cisnienie absolutne
double const sg = PL / PH; // bezwymiarowy stosunek cisnien
double const FM = PH * 197.0 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem
if (sg > 0.5) // jesli ponizej stosunku krytycznego
if ((PH - PL) < DP) // niewielka roznica cisnien
return (1.0 - sg) / DPL * FM * 2.0 * std::sqrt((DP) * (PH - DP));
@@ -69,15 +70,15 @@ double PF1( double const P1, double const P2, double const S )
{
static double const DPS = 0.001;
double PH = std::max(P1, P2) + 1; // wyzsze cisnienie absolutne
double PL = P1 + P2 - PH + 2; // nizsze cisnienie absolutne
double sg = PL / PH; // bezwymiarowy stosunek cisnien
double FM = PH * 197 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem
if ((sg > 0.5)) // jesli ponizej stosunku krytycznego
if ((sg < DPS)) // niewielka roznica cisnien
return (1 - sg) / DPS * FM * 2 * std::sqrt((DPS) * (1 - DPS));
double const PH = std::max(P1, P2) + 1.0; // wyzsze cisnienie absolutne
double const PL = P1 + P2 - PH + 2.0; // nizsze cisnienie absolutne
double const sg = PL / PH; // bezwymiarowy stosunek cisnien
double const FM = PH * 197.0 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem
if (sg > 0.5) // jesli ponizej stosunku krytycznego
if (sg < DPS) // niewielka roznica cisnien
return (1.0 - sg) / DPS * FM * 2.0 * std::sqrt((DPS) * (1.0 - DPS));
else
return FM * 2 * std::sqrt((sg) * (1 - sg));
return FM * 2.0 * std::sqrt((sg) * (1.0 - sg));
else // powyzej stosunku krytycznego
return FM;
}
@@ -1184,50 +1185,50 @@ void TESt3AL2::Init( double const PP, double const HPP, double const LPP, double
double TLSt::GetPF( double const PP, double const dt, double const Vel )
{
double result;
double dv;
double dV1;
double temp;
double VVP;
double BVP;
double BCP;
double CVP;
// ValveRes.CreatePress(LBP);
// LBP:=0;
BVP = BrakeRes->P();
VVP = ValveRes->P();
BCP = ImplsRes->P();
CVP = CntrlRes->P();
double const BVP{ BrakeRes->P() };
double const VVP{ ValveRes->P() };
double const BCP{ ImplsRes->P() };
double const CVP{ CntrlRes->P() };
dv = 0;
dV1 = 0;
double dV{ 0.0 };
double dV1{ 0.0 };
// sprawdzanie stanu
if ((BrakeStatus & b_rls) == b_rls)
if ((CVP < 0))
if( ( BrakeStatus & b_rls ) == b_rls ) {
if( CVP < 0.0 ) {
BrakeStatus &= ~b_rls;
}
else
{ // 008
dv = PF1(CVP, BCP, 0.024) * dt;
CntrlRes->Flow(+dv);
// dV1:=+dV; //minus potem jest
// ImplsRes->Flow(-dV1);
dV = PF1( CVP, BCP, 0.024 ) * dt;
CntrlRes->Flow( dV );
/*
// NOTE: attempted fix, disabled because it breaks when releaser is used while releasing breakes
dV = PF1(CVP, VVP, 0.024) * dt;
CntrlRes->Flow( dV );
dV1 = dV; //minus potem jest
ImplsRes->Flow( -dV1 );
*/
}
}
VVP = ValveRes->P();
double temp;
// przeplyw ZS <-> PG
if (((CVP - BCP) * BVM > 0.5))
temp = 0;
temp = 0.0;
else if ((VVP > CVP + 0.4))
temp = 0.5;
else
temp = 0.5;
dv = PF1(CVP, VVP, 0.0015 * temp / 1.8 / 2) * dt;
CntrlRes->Flow(+dv);
ValveRes->Flow(-0.04 * dv);
dV1 = dV1 - 0.96 * dv;
dV = PF1(CVP, VVP, 0.0015 * temp / 1.8 / 2) * dt;
CntrlRes->Flow(+dV);
ValveRes->Flow(-0.04 * dV);
dV1 = dV1 - 0.96 * dV;
// luzowanie KI {G}
// if VVP>BCP then
@@ -1236,26 +1237,38 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel )
// dV:=PF(VVP,BCP,0.00020*(1.33-int((CVP-BCP)*BVM>0.65)))*dt
// else dV:=0; 0.00025 P
/*P*/
if (VVP > BCP)
dv = PF(VVP, BCP,
0.00043 * (1.5 - int(((CVP - BCP) * BVM > 1) && (BrakeDelayFlag == bdelay_G))),
0.1) *
dt;
else if ((CVP - BCP) < 1.5)
dv = PF(VVP, BCP,
0.001472 * (1.36 - int(((CVP - BCP) * BVM > 1) && (BrakeDelayFlag == bdelay_G))),
0.1) *
dt;
else
dv = 0;
if( VVP > BCP ) {
dV =
PF( VVP, BCP,
0.00043 * ( 1.5 - (
true == ( ( ( CVP - BCP ) * BVM > 1.0 )
&& ( BrakeDelayFlag == bdelay_G ) ) ?
1.0 :
0.0 ) ),
0.1 )
* dt;
}
else if( ( CVP - BCP ) < 1.5 ) {
dV = PF( VVP, BCP,
0.001472 * ( 1.36 - (
true == ( ( ( CVP - BCP ) * BVM > 1.0 )
&& ( BrakeDelayFlag == bdelay_G ) ) ?
1.0 :
0.0 ) ),
0.1 )
* dt;
}
else {
dV = 0;
}
ImplsRes->Flow(-dv);
ValveRes->Flow(+dv);
ImplsRes->Flow(-dV);
ValveRes->Flow(+dV);
// przeplyw PG <-> rozdzielacz
dv = PF(PP, VVP, 0.01, 0.1) * dt;
ValveRes->Flow(-dv);
dV = PF(PP, VVP, 0.01, 0.1) * dt;
ValveRes->Flow(-dV);
result = dv - dV1;
result = dV - dV1;
// if Vel>55 then temp:=0.72 else
// temp:=1;{R}
@@ -1272,18 +1285,18 @@ double TLSt::GetPF( double const PP, double const dt, double const Vel )
if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28))
// dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt
// dV:=PF(0,BrakeCyl->P(),0.005*3*sizeBC)*dt
dv = PFVd(BrakeCyl->P(), 0, 0.005 * 7 * SizeBC, temp) * dt;
dV = PFVd(BrakeCyl->P(), 0, 0.005 * 7 * SizeBC, temp) * dt;
else
dv = 0;
BrakeCyl->Flow(-dv);
dV = 0;
BrakeCyl->Flow(-dV);
// przeplyw ZP <-> CH
if ((BrakeCyl->P() < temp - 0.005) && (temp > 0.29))
// dV:=PF(BVP,BrakeCyl->P(),0.002*3*sizeBC*2)*dt
dv = -PFVa(BVP, BrakeCyl->P(), 0.002 * 7 * SizeBC * 2, temp) * dt;
dV = -PFVa(BVP, BrakeCyl->P(), 0.002 * 7 * SizeBC * 2, temp) * dt;
else
dv = 0;
BrakeRes->Flow(dv);
BrakeCyl->Flow(-dv);
dV = 0;
BrakeRes->Flow(dV);
BrakeCyl->Flow(-dV);
ImplsRes->Act();
ValveRes->Act();
@@ -2198,124 +2211,145 @@ double TFV4aM::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
static int const LBDelay = 100;
static double const xpM = 0.3; // mnoznik membrany komory pod
double LimPP;
double dpPipe;
double dpMainValve;
double ActFlowSpeed;
double DP;
double pom;
int i;
ep = (PP / 2.0) * 1.5 + (ep / 2.0) * 0.5; // SPKS!!
ep = PP / 2 * 1.5 + ep / 2 * 0.5; // SPKS!!
// ep:=pp;
// ep:=cp/3+pp/3+ep/3;
// ep:=cp;
for( int idx = 0; idx < 5; ++idx ) {
Sounds[ idx ] = 0;
}
for (i = 0; i < 5; ++i)
Sounds[i] = 0;
DP = 0;
// na wszelki wypadek, zeby nie wyszlo poza zakres
i_bcp = clamp( i_bcp, -1.999, 5.999 );
i_bcp = Max0R(Min0R(i_bcp, 5.999), -1.999); // na wszelki wypadek, zeby nie wyszlo poza zakres
if ((TP > 0))
{ // jesli czasowy jest niepusty
// dp:=0.07; //od cisnienia 5 do 0 w 60 sekund ((5-0)*dt/75)
double DP{ 0.0 };
if( TP > 0.0 ) {
// jesli czasowy jest niepusty
DP = 0.045; // 2.5 w 55 sekund (5,35->5,15 w PG)
TP = TP - DP * dt;
TP -= DP * dt;
Sounds[s_fv4a_t] = DP;
}
else //.08
{
TP = 0;
else {
//.08
TP = 0.0;
}
if ((XP > 0)) // jesli komora pod niepusta jest niepusty
{
if (XP > 0) {
// jesli komora pod niepusta jest niepusty
DP = 2.5;
Sounds[s_fv4a_x] = DP * XP;
XP = XP - dt * DP * 2; // od cisnienia 5 do 0 w 10 sekund ((5-0)*dt/10)
XP -= dt * DP * 2.0; // od cisnienia 5 do 0 w 10 sekund ((5-0)*dt/10)
}
else {
// jak pusty, to pusty
XP = 0.0;
}
else //.75
XP = 0; // jak pusty, to pusty
LimPP = Min0R(LPP_RP(i_bcp) + TP * 0.08 + RedAdj, HP); // pozycja + czasowy lub zasilanie
ActFlowSpeed = BPT[lround(i_bcp) + 2][0];
double pom;
if( EQ( i_bcp, -1.0 ) ) {
pom = std::min( HP, 5.4 + RedAdj );
}
else {
pom = std::min( CP, HP );
}
if ((EQ(i_bcp, -1)))
pom = Min0R(HP, 5.4 + RedAdj);
else
pom = Min0R(CP, HP);
if ((pom > RP + 0.25))
if( pom > RP + 0.25 ) {
Fala = true;
if ((Fala))
if ((pom > RP + 0.3))
// if(ep>rp+0.11)then
XP = XP - 20 * PR(pom, XP) * dt;
// else
// xp:=xp-16*(ep-(ep+0.01))/(0.1)*PR(ep,xp)*dt;
else
}
if( Fala ) {
if( pom > RP + 0.3 ) {
XP = XP - 20.0 * PR( pom, XP ) * dt;
}
else {
Fala = false;
}
}
if ((LimPP > CP)) // podwyzszanie szybkie
CP = CP + 5 * 60 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy;
else
CP = CP + 13 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy
double LimPP = std::min(
LPP_RP( i_bcp ) + TP * 0.08 + RedAdj,
HP ); // pozycja + czasowy lub zasilanie
// zbiornik sterujacy
if( LimPP > CP ) {
// podwyzszanie szybkie
CP +=
5.0 * 60.0
* std::min(
std::abs( LimPP - CP ),
0.05 )
* PR( CP, LimPP )
* dt;
}
else {
CP +=
13
* std::min(
std::abs( LimPP - CP ),
0.05 )
* PR( CP, LimPP )
* dt;
}
LimPP = pom; // cp
dpPipe = Min0R(HP, LimPP + XP * xpM);
double const dpPipe = std::min(HP, LimPP + XP * xpM);
if (dpPipe > PP)
dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4);
else
dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4);
double const ActFlowSpeed = BPT[ std::lround( i_bcp ) + 2 ][ 0 ];
if (EQ(i_bcp, -1))
{
if ((TP < 5))
TP = TP + dt; // 5/10
if ((TP < 1))
TP = TP - 0.5 * dt; // 5/10
// dpMainValve:=dpMainValve*2;
//+1*PF(dpPipe,pp,ActFlowSpeed/LBDelay)//coby
// nie przeszkadzal przy ladowaniu z zaworu obok
double dpMainValve;
if( dpPipe > PP ) {
dpMainValve = -PFVa( HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4 );
}
else {
dpMainValve = PFVd( PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4 );
}
if (EQ(i_bcp, 0))
{
if ((TP > 2))
dpMainValve = dpMainValve * 1.5; //+0.5*PF(dpPipe,pp,ActFlowSpeed/LBDelay)//coby nie
// przeszkadzal przy ladowaniu z zaworu obok
if (EQ(i_bcp, -1)) {
if( TP < 5 ) { TP += dt; }
if( TP < 1 ) { TP -= 0.5 * dt; }
}
if (EQ(i_bcp, 0)) {
if( TP > 2 ) {
dpMainValve *= 1.5;
}
}
ep = dpPipe;
if ((EQ(i_bcp, 0) || (RP > ep)))
RP = RP + PF(RP, ep, 0.0007) * dt; // powolne wzrastanie, ale szybsze na jezdzie;
else
RP = RP + PF(RP, ep, 0.000093 / 2 * 2) * dt; // powolne wzrastanie i to bardzo
// jednak trzeba wydluzyc, bo
// obecnie zle dziala
if ((RP < ep) &&
(RP <
BPT[lround(i_bcpno) + 2][1])) // jesli jestesmy ponizej cisnienia w sterujacym (2.9 bar)
RP = RP + PF(RP, CP, 0.005) * dt; // przypisz cisnienie w PG - wydluzanie napelniania o czas
// potrzebny do napelnienia PG
if( ( EQ( i_bcp, 0 )
|| ( RP > ep ) ) ) {
// powolne wzrastanie, ale szybsze na jezdzie;
RP += PF( RP, ep, 0.0007 ) * dt;
}
else {
// powolne wzrastanie i to bardzo
RP += PF( RP, ep, 0.000093 / 2 * 2 ) * dt;
}
// jednak trzeba wydluzyc, bo obecnie zle dziala
if( ( RP < ep )
&& ( RP < BPT[ std::lround( i_bcpno ) + 2 ][ 1 ] ) ) {
// jesli jestesmy ponizej cisnienia w sterujacym (2.9 bar)
// przypisz cisnienie w PG - wydluzanie napelniania o czas potrzebny do napelnienia PG
RP += PF( RP, CP, 0.005 ) * dt;
}
if ((EQ(i_bcp, i_bcpno)) || (EQ(i_bcp, -2)))
{
DP = PF(0, PP, ActFlowSpeed / LBDelay);
if( ( EQ( i_bcp, i_bcpno ) )
|| ( EQ( i_bcp, -2 ) ) ) {
DP = PF( 0.0, PP, ActFlowSpeed / LBDelay );
dpMainValve = DP;
Sounds[s_fv4a_e] = DP;
Sounds[s_fv4a_u] = 0;
Sounds[s_fv4a_b] = 0;
Sounds[s_fv4a_x] = 0;
Sounds[s_fv4a_u] = 0.0;
Sounds[s_fv4a_b] = 0.0;
Sounds[s_fv4a_x] = 0.0;
}
else
{
if (dpMainValve > 0)
Sounds[s_fv4a_b] = dpMainValve;
else
Sounds[s_fv4a_u] = -dpMainValve;
else {
if( dpMainValve > 0.0 ) {
Sounds[ s_fv4a_b ] = dpMainValve;
}
else {
Sounds[ s_fv4a_u ] = -dpMainValve;
}
}
return dpMainValve * dt;
@@ -2347,17 +2381,11 @@ double TFV4aM::GetPos(int i)
double TFV4aM::LPP_RP(double pos) // cisnienie z zaokraglonej pozycji;
{
int i_pos;
int const i_pos = 2 + std::floor( pos ); // zaokraglone w dol
i_pos = lround(pos - 0.5) + 2; // zaokraglone w dol
double i, j, k, l;
i = BPT[i_pos][1];
j = BPT[i_pos + 1][1];
k = pos + 2 - i_pos;
l = i + (j - i) * k;
double r = BPT[i_pos][1] +
(BPT[i_pos + 1][1] - BPT[i_pos][1]) * (pos + 2 - i_pos); // interpolacja liniowa
return r;
return
BPT[i_pos][1]
+ (BPT[i_pos + 1][1] - BPT[i_pos][1]) * ((pos + 2) - i_pos); // interpolacja liniowa
}
bool TFV4aM::EQ(double pos, double i_pos)
{
@@ -2366,8 +2394,7 @@ bool TFV4aM::EQ(double pos, double i_pos)
//---FV4a/M--- nowonapisany kran bez poprawki IC
double TMHZ_EN57::GetPF(double i_bcp, double PP, double HP, double dt, double ep)
{
double TMHZ_EN57::GetPF( double i_bcp, double PP, double HP, double dt, double ep ) {
static int const LBDelay = 100;
double LimPP;
@@ -2376,13 +2403,11 @@ double TMHZ_EN57::GetPF(double i_bcp, double PP, double HP, double dt, double ep
double ActFlowSpeed;
double DP;
double pom;
int i;
{
long i_end = 5;
for (i = 0; i < i_end; ++i)
Sounds[i] = 0;
for( int idx = 0; idx < 5; ++idx ) {
Sounds[ idx ] = 0;
}
DP = 0;
i_bcp = Max0R(Min0R(i_bcp, 9.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres

View File

@@ -184,7 +184,7 @@ class TBrake {
bool DCV = false; //podwojny zawor zwrotny
double ASBP = 0.0; //cisnienie hamulca pp
int BrakeStatus = 0; //flaga stanu
int BrakeStatus{ b_off }; //flaga stanu
int SoundFlag = 0;
public:
@@ -213,6 +213,8 @@ class TBrake {
void SetASBP( double const Press ); //ustalenie cisnienia pp
virtual void ForceEmptiness();
int GetSoundFlag();
int GetBrakeStatus() const { return BrakeStatus; }
void SetBrakeStatus( int const Status ) { BrakeStatus = Status; }
virtual void SetED( double const EDstate ) {}; //stan hamulca ED do luzowania
};

View File

@@ -144,98 +144,6 @@ bool FuzzyLogicAI(double Test, double Threshold, double Probability)
return false;
}
std::string ReadWord(std::ifstream &infile)
{
std::string s = "";
char c;
bool nextword = false;
while ((!infile.eof()) && (!nextword))
{
infile.get(c);
if (_spacesigns.find(c) != std::string::npos)
if (s != "")
nextword = true;
if (_spacesigns.find(c) == std::string::npos)
s += c;
}
return s;
}
std::string TrimSpace(std::string &s)
{
/*int ii;
switch (Just)
{
case CutLeft:
{
ii = 0;
while ((ii < s.length()) && (s[ii + 1] == (char)" "))
++ii;
s = s.substr(ii + 1, s.length() - ii);
}
case CutRight:
{
ii = s.length();
while ((ii > 0) && (s[ii] == (char)" "))
--ii;
s = s.substr(0, ii);
}
case CutBoth:
{
s = TrimSpace(s, CutLeft);
s = TrimSpace(s, CutRight);
}
}
return s;*/
if (s.empty())
return "";
size_t first = s.find_first_not_of(' ');
if (first == std::string::npos)
return "";
size_t last = s.find_last_not_of(' ');
return s.substr(first, (last - first + 1));
}
char* TrimAndReduceSpaces(const char* s)
{ // redukuje spacje pomiedzy znakami do jednej
char* tmp = nullptr;
if (s)
{
tmp = _strdup(s);
char* from = tmp + strspn(tmp, " ");
char* to = tmp;
do if ((*to = *from++) == ' ')
from += strspn(from, " ");
while (*to++);
while (*--to == ' ')
*to = '\0';
}
return tmp;
}
std::string ExtractKeyWord(std::string InS, std::string KeyWord)
{
std::string s;
InS = InS + " ";
std::size_t kwp = InS.find(KeyWord);
if (kwp != std::string::npos)
{
s = InS.substr(kwp, InS.length());
//s = Copy(InS, kwp, length(InS));
s = s.substr(0, s.find_first_of(" "));
//s = Copy(s, 1, Pos(" ", s) - 1);
}
else
s = "";
return s;
}
std::string DUE(std::string s) /*Delete Before Equal sign*/
{
//DUE = Copy(s, Pos("=", s) + 1, length(s));
@@ -473,8 +381,7 @@ void ComputeALine(double X0, double Y0, double Xn, double Yn, double L, double R
bool FileExists( std::string const &Filename ) {
std::ifstream file( Filename );
if( file.is_open() == false ) { return false; }
else { return true; }
return( true == file.is_open() );
}
/*

View File

@@ -105,11 +105,6 @@ bool FuzzyLogicAI(double Test, double Threshold, double Probability);
/*to samo ale zawsze niezaleznie od DebugFlag*/
/*operacje na stringach*/
std::string ReadWord( std::ifstream& infile); /*czyta slowo z wiersza pliku tekstowego*/
//std::string Ups(std::string s);
//std::string TrimSpace(std::string &s);
//char* TrimAndReduceSpaces(const char* s);
//std::string ExtractKeyWord(std::string InS, std::string KeyWord); /*wyciaga slowo kluczowe i lancuch do pierwszej spacji*/
std::string DUE(std::string s); /*Delete Until Equal sign*/
std::string DWE(std::string s); /*Delete While Equal sign*/
std::string ExchangeCharInString(std::string const &s, const char &aim, const char &target); // zamienia jeden znak na drugi

View File

@@ -56,7 +56,8 @@ void TModelsManager::Init()
*/
void TModelsManager::Free()
{
SafeDeleteArray(Models);
delete[] Models;
Models = nullptr;
}
TModel3d * TModelsManager::LoadModel(std::string const &Name, bool dynamic)

View File

@@ -14,16 +14,12 @@ http://mozilla.org/MPL/2.0/.
class TMdlContainer
{
friend class TModelsManager;
TMdlContainer()
{
Model = NULL;
};
~TMdlContainer()
{
SafeDelete(Model);
delete Model;
};
TModel3d * LoadModel(std::string const &NewName, bool dynamic);
TModel3d *Model;
TModel3d *Model{ nullptr };
std::string Name;
};

View File

@@ -973,357 +973,6 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
}
};
#ifdef EU07_USE_OLD_RENDERCODE
void TSubModel::RenderDL()
{ // główna procedura renderowania przez DL
return;
if( ( iVisible )
&& ( fSquareDist >= (fSquareMinDist / Global::fDistanceFactor) )
&& ( fSquareDist <= (fSquareMaxDist * Global::fDistanceFactor) ) )
{
if (iFlags & 0xC000)
{
glPushMatrix();
if (fMatrix)
glMultMatrixf(fMatrix->readArray());
// if (b_Anim)
// RaAnimation(b_Anim);
}
if (eType < TP_ROTATOR)
{ // renderowanie obiektów OpenGL
if (iAlpha & iFlags & 0x1F) // rysuj gdy element nieprzezroczysty
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=!(iAlpha&1); //zmiana tylko w przypadku wymienej tekstury
}
else
GfxRenderer.Bind(TextureID); // również 0
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glCallList(uiDisplayList); // tylko dla siatki
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
else
glCallList(uiDisplayList); // tylko dla siatki
}
}
else if (eType == TP_FREESPOTLIGHT)
{ // wersja DL
matrix4x4 mat; // macierz opisuje układ renderowania względem kamery
glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray());
// kąt między kierunkiem światła a współrzędnymi kamery
vector3 gdzie = mat * vector3(0, 0, 0); // pozycja punktu świecącego względem kamery
fCosViewAngle = DotProduct(Normalize(mat * vector3(0, 0, 1) - gdzie), Normalize(gdzie));
if (fCosViewAngle > fCosFalloffAngle) // kąt większy niż maksymalny stożek swiatła
{
double Distdimm = 1.0;
if (fCosViewAngle <
fCosHotspotAngle) // zmniejszona jasność między Hotspot a Falloff
if (fCosFalloffAngle < fCosHotspotAngle)
Distdimm = 1.0 -
(fCosHotspotAngle - fCosViewAngle) /
(fCosHotspotAngle - fCosFalloffAngle);
glColor3f(f4Diffuse[0] * Distdimm, f4Diffuse[1] * Distdimm,
f4Diffuse[2] * Distdimm);
/* TODO: poprawic to zeby dzialalo
if (iFarAttenDecay>0)
switch (iFarAttenDecay)
{
case 1:
Distdimm=fFarDecayRadius/(1+sqrt(fSquareDist));
//dorobic od kata
break;
case 2:
Distdimm=fFarDecayRadius/(1+fSquareDist);
//dorobic od kata
break;
}
if (Distdimm>1)
Distdimm=1;
glColor3f(Diffuse[0]*Distdimm,Diffuse[1]*Distdimm,Diffuse[2]*Distdimm);
*/
// glPopMatrix();
// return;
glCallList(uiDisplayList); // wyświetlenie warunkowe
}
}
else if (eType == TP_STARS)
{
// glDisable(GL_LIGHTING); //Tolaris-030603: bo mu punkty swiecace sie
// blendowaly
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glCallList(uiDisplayList); // narysuj naraz wszystkie punkty z DL
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
}
if (Child != NULL)
if (iAlpha & iFlags & 0x001F0000)
Child->RenderDL();
if (iFlags & 0xC000)
glPopMatrix();
}
if (b_Anim < at_SecondsJump)
b_Anim = at_None; // wyłączenie animacji dla kolejnego użycia subm
if (Next)
if (iAlpha & iFlags & 0x1F000000)
Next->RenderDL(); // dalsze rekurencyjnie
}; // Render
void TSubModel::RenderAlphaDL()
{ // renderowanie przezroczystych przez DL
return;
if( ( iVisible )
&& ( fSquareDist >= (fSquareMinDist / Global::fDistanceFactor) )
&& ( fSquareDist <= (fSquareMaxDist * Global::fDistanceFactor) ) )
{
if (iFlags & 0xC000)
{
glPushMatrix();
if (fMatrix)
glMultMatrixf(fMatrix->readArray());
// if (b_aAnim)
// RaAnimation(b_aAnim);
}
if (eType < TP_ROTATOR)
{ // renderowanie obiektów OpenGL
if (iAlpha & iFlags & 0x2F) // rysuj gdy element przezroczysty
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=iAlpha&1; //zmiana tylko w przypadku wymienej tekstury
}
else
GfxRenderer.Bind(TextureID); // również 0
if (Global::fLuminance < fLight)
{
glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glCallList(uiDisplayList); // tylko dla siatki
glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
else
glCallList(uiDisplayList); // tylko dla siatki
}
}
else if (eType == TP_FREESPOTLIGHT)
{
// dorobić aureolę!
}
if (Child != NULL)
if (eType == TP_TEXT)
{ // tekst renderujemy w specjalny sposób, zamiast
// submodeli z łańcucha Child
int i, j = (int)pasText->size();
TSubModel *p;
if (!smLetter)
{ // jeśli nie ma tablicy, to ją stworzyć; miejsce
// nieodpowiednie, ale tymczasowo
// może być
smLetter = new TSubModel *[256]; // tablica wskaźników submodeli dla
// wyświetlania tekstu
ZeroMemory(smLetter, 256 * sizeof(TSubModel *)); // wypełnianie zerami
p = Child;
while (p)
{
smLetter[p->pName[0]] = p;
p = p->Next; // kolejny znak
}
}
for (i = 1; i <= j; ++i)
{
p = smLetter[(*pasText)[i]]; // znak do wyświetlenia
if (p)
{ // na razie tylko jako przezroczyste
p->RenderAlphaDL();
if (p->fMatrix)
glMultMatrixf(p->fMatrix->readArray()); // przesuwanie widoku
}
}
}
else if (iAlpha & iFlags & 0x002F0000)
Child->RenderAlphaDL();
if (iFlags & 0xC000)
glPopMatrix();
}
if (b_aAnim < at_SecondsJump)
b_aAnim = at_None; // wyłączenie animacji dla kolejnego użycia submodelu
if (Next != NULL)
if (iAlpha & iFlags & 0x2F000000)
Next->RenderAlphaDL();
}; // RenderAlpha
void TSubModel::RenderVBO(glm::mat4 m)
{ // główna procedura renderowania przez VBO
if( ( iVisible )
&& ( fSquareDist >= (fSquareMinDist / Global::fDistanceFactor) )
&& ( fSquareDist <= (fSquareMaxDist * Global::fDistanceFactor) ) )
{
glm::mat4 mm = m;
if (iFlags & 0xC000)
{
if (fMatrix)
mm *= glm::make_mat4(fMatrix->e);
if (b_Anim)
RaAnimation(mm, b_Anim);
World.shader.set_mv(mm);
}
if (eType < TP_ROTATOR)
{ // renderowanie obiektów OpenGL
if (iAlpha & iFlags & 0x1F) // rysuj gdy element nieprzezroczysty
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skóry
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
}
else
GfxRenderer.Bind(TextureID); // również 0
//glColor3fv(f4Diffuse); // McZapkie-240702: zamiast ub
if (Global::fLuminance < fLight)
{
//glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glDrawArrays(eType, iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
//glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
else
glDrawArrays(eType, iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
}
}
else if (eType == TP_FREESPOTLIGHT)
{ // wersja VBO
/*
matrix4x4 mat; // macierz opisuje układ renderowania względem kamery
glGetDoublev(GL_MODELVIEW_MATRIX, mat.getArray());
*/
matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
// kąt między kierunkiem światła a współrzędnymi kamery
vector3 gdzie = mat * vector3(0, 0, 0); // pozycja punktu świecącego względem kamery
fCosViewAngle = DotProduct(Normalize(mat * vector3(0, 0, 1) - gdzie), Normalize(gdzie));
if (fCosViewAngle > fCosFalloffAngle) // kąt większy niż maksymalny stożek swiatła
{
double Distdimm = 1.0;
if (fCosViewAngle <
fCosHotspotAngle) // zmniejszona jasność między Hotspot a Falloff
if (fCosFalloffAngle < fCosHotspotAngle)
Distdimm = 1.0 -
(fCosHotspotAngle - fCosViewAngle) /
(fCosHotspotAngle - fCosFalloffAngle);
GfxRenderer.Bind(0); // nie teksturować
float color[4] = { (float)(f4Diffuse[0] * Distdimm), (float)(f4Diffuse[1] * Distdimm),
(float)(f4Diffuse[2] * Distdimm), 0 };
//glColorMaterial(GL_FRONT, GL_EMISSION);
//glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie blendowaly
//glColor3fv(color); // inaczej są białe
//glMaterialfv(GL_FRONT, GL_EMISSION, color);
glDrawArrays(GL_POINTS, iVboPtr, iNumVerts); // narysuj wierzchołek z VBO
//glEnable(GL_LIGHTING);
//glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // co ma ustawiać glColor
//glMaterialfv(GL_FRONT, GL_EMISSION, emm2); // bez tego słupy się świecą
}
}
else if (eType == TP_STARS)
{
if (Global::fLuminance < fLight)
{ // Ra: pewnie można by to zrobić
// lepiej, bez powtarzania StartVBO()
pRoot->EndVBO(); // Ra: to też nie jest zbyt ładne
if (pRoot->StartColorVBO())
{ // wyświetlanie kolorowych punktów zamiast
// trójkątów
GfxRenderer.Bind(0); // tekstury nie ma
glColorMaterial(GL_FRONT, GL_EMISSION);
glDisable(GL_LIGHTING); // Tolaris-030603: bo mu punkty swiecace sie
// blendowaly
// glMaterialfv(GL_FRONT,GL_EMISSION,f4Diffuse); //zeby swiecilo na
// kolorowo
glDrawArrays(GL_POINTS, iVboPtr,
iNumVerts); // narysuj naraz wszystkie punkty z VBO
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// glMaterialfv(GL_FRONT,GL_EMISSION,emm2);
pRoot->EndVBO();
pRoot->StartVBO();
}
}
}
if (Child != NULL)
if (iAlpha & iFlags & 0x001F0000)
Child->RenderVBO(mm);
if (iFlags & 0xC000)
World.shader.set_mv(m);
}
if (b_Anim < at_SecondsJump)
b_Anim = at_None; // wyłączenie animacji dla kolejnego użycia submodelu
if (Next)
if (iAlpha & iFlags & 0x1F000000)
Next->RenderVBO(m); // dalsze rekurencyjnie
}; // RaRender
void TSubModel::RenderAlphaVBO(glm::mat4 m)
{ // renderowanie przezroczystych przez VBO
if( ( iVisible )
&& ( fSquareDist >= (fSquareMinDist / Global::fDistanceFactor) )
&& ( fSquareDist <= (fSquareMaxDist * Global::fDistanceFactor) ) )
{
glm::mat4 mm = m;
if (iFlags & 0xC000)
{
if (fMatrix)
mm *= glm::make_mat4(fMatrix->e);
if (b_Anim)
RaAnimation(mm, b_Anim);
World.shader.set_mv(mm);
}
if (eType < TP_ROTATOR)
{ // renderowanie obiektów OpenGL
if (iAlpha & iFlags & 0x2F) // rysuj gdy element przezroczysty
{
if (TextureID < 0) // && (ReplacableSkinId!=0))
{ // zmienialne skory
GfxRenderer.Bind(ReplacableSkinId[-TextureID]);
// TexAlpha=iAlpha&1; //zmiana tylko w przypadku wymienej tekstury
}
else
GfxRenderer.Bind(TextureID); // również 0
if (Global::fLuminance < fLight)
{
//glMaterialfv(GL_FRONT, GL_EMISSION, f4Diffuse); // zeby swiecilo na kolorowo
glDrawArrays(eType, iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
//glMaterialfv(GL_FRONT, GL_EMISSION, emm2);
}
else
glDrawArrays(eType, iVboPtr,
iNumVerts); // narysuj naraz wszystkie trójkąty z VBO
}
}
else if (eType == TP_FREESPOTLIGHT)
{
// dorobić aureolę!
}
if (Child)
if (iAlpha & iFlags & 0x002F0000)
Child->RenderAlphaVBO(mm);
if (iFlags & 0xC000)
World.shader.set_mv(m);
}
if (b_aAnim < at_SecondsJump)
b_aAnim = at_None; // wyłączenie animacji dla kolejnego użycia submodelu
if (Next)
if (iAlpha & iFlags & 0x2F000000)
Next->RenderAlphaVBO(m);
}; // RaRenderAlpha
#endif
//---------------------------------------------------------------------------
void TSubModel::RaArrayFill(CVertNormTex *Vert)
@@ -1450,8 +1099,12 @@ TModel3d::~TModel3d()
}
else
{ // wczytano z pliku binarnego (jest właścicielem tablic)
m_pVNT = NULL; // nie usuwać tego, bo wskazuje na iModel
Root = NULL;
#ifdef EU07_USE_OLD_VERTEXBUFFER
m_pVNT = nullptr; // nie usuwać tego, bo wskazuje na iModel
#else
m_pVNT.clear();
#endif
Root = nullptr;
delete[] iModel; // usuwamy cały wczytany plik i to wystarczy
}
// później się jeszcze usuwa obiekt z którego dziedziczymy tabelę VBO
@@ -1674,7 +1327,11 @@ void TModel3d::SaveToBinFile(char const *FileName)
transforms[i].serialize_float32(s);
MakeArray(iNumVerts);
Root->RaArrayFill(m_pVNT);
#ifdef EU07_USE_OLD_VERTEXBUFFER
Root->RaArrayFill(m_pVNT);
#else
Root->RaArrayFill( m_pVNT.data() );
#endif
sn_utils::ls_uint32(s, MAKE_ID4('V', 'N', 'T', '0'));
sn_utils::ls_uint32(s, 8 + iNumVerts * 32);
for (size_t i = 0; i < (size_t)iNumVerts; i++)
@@ -1759,7 +1416,11 @@ void TSubModel::deserialize(std::istream &s)
void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
{
m_pVNT = nullptr;
#ifdef EU07_USE_OLD_VERTEXBUFFER
m_pVNT = nullptr;
#else
m_pVNT.clear();
#endif
Root = nullptr;
float4x4 *tm = nullptr;
@@ -1773,13 +1434,22 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
if (type == MAKE_ID4('V', 'N', 'T', '0'))
{
if (m_pVNT != nullptr)
#ifdef EU07_USE_OLD_VERTEXBUFFER
if (m_pVNT != nullptr)
#else
if( false == m_pVNT.empty() )
#endif
throw std::runtime_error("e3d: duplicated VNT chunk");
size_t vt_cnt = size / 32;
iNumVerts = (int)vt_cnt;
m_nVertexCount = (int)vt_cnt;
m_pVNT = new CVertNormTex[vt_cnt];
#ifdef EU07_USE_OLD_VERTEXBUFFER
assert( m_pVNT == nullptr );
m_pVNT = new CVertNormTex[vt_cnt];
#else
m_pVNT.resize( vt_cnt );
#endif
for (size_t i = 0; i < vt_cnt; i++)
m_pVNT[i].deserialize(s);
}
@@ -1840,12 +1510,20 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
if (!Root)
throw std::runtime_error("e3d: no submodels");
if (!m_pVNT)
#ifdef EU07_USE_OLD_VERTEXBUFFER
if (!m_pVNT)
#else
if(m_pVNT.empty() )
#endif
throw std::runtime_error("e3d: no vertices");
for (size_t i = 0; (int)i < iSubModelsCount; i++)
{
Root[i].BinInit(Root, tm, (float8*)m_pVNT, &Textures, &Names, dynamic);
#ifdef EU07_USE_OLD_VERTEXBUFFER
Root[i].BinInit(Root, tm, (float8*)m_pVNT, &Textures, &Names, dynamic);
#else
Root[ i ].BinInit( Root, tm, (float8*)m_pVNT.data(), &Textures, &Names, dynamic );
#endif
if (Root[i].ChildGet())
Root[i].ChildGet()->Parent = &Root[i];
@@ -2019,11 +1697,18 @@ void TModel3d::Init()
Root->AdjustDist(); // aktualizacja odległości faz LoD, zależnie od
// rozdzielczości pionowej oraz multisamplingu
*/
if (!m_pVNT) // jeśli nie ma jeszcze tablicy (wczytano z pliku
// tekstowego)
#ifdef EU07_USE_OLD_VERTEXBUFFER
if (!m_pVNT) // jeśli nie ma jeszcze tablicy (wczytano z pliku tekstowego)
#else
if( m_pVNT.empty() )
#endif
{ // tworzenie tymczasowej tablicy z wierzchołkami całego modelu
MakeArray(iNumVerts); // tworzenie tablic dla VBO
Root->RaArrayFill(m_pVNT); // wypełnianie tablicy
#ifdef EU07_USE_OLD_VERTEXBUFFER
Root->RaArrayFill(m_pVNT); // wypełnianie tablicy
#else
Root->RaArrayFill( m_pVNT.data() ); // wypełnianie tablicy
#endif
BuildVBOs(); // tworzenie VBO i usuwanie tablicy z pamięci
}
else
@@ -2039,168 +1724,6 @@ void TModel3d::BreakHierarhy()
Error("Not implemented yet :(");
};
#ifdef EU07_USE_OLD_RENDERCODE
void TModel3d::Render(double fSquareDistance, texture_manager::size_type *ReplacableSkinId, int iAlpha)
{
iAlpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste
if (iAlpha & iFlags & 0x1F1F001F) // czy w ogóle jest co robić w tym cyklu?
{
TSubModel::fSquareDist = fSquareDistance; // zmienna globalna!
Root->ReplacableSet(ReplacableSkinId, iAlpha);
Root->RenderDL();
}
};
void TModel3d::RenderAlpha(double fSquareDistance, texture_manager::size_type *ReplacableSkinId, int iAlpha)
{
if (iAlpha & iFlags & 0x2F2F002F)
{
TSubModel::fSquareDist = fSquareDistance; // zmienna globalna!
Root->ReplacableSet(ReplacableSkinId, iAlpha);
Root->RenderAlphaDL();
}
};
void TModel3d::RaRender(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
{ // renderowanie specjalne, np. kabiny
iAlpha ^= 0x0F0F000F; // odwrócenie flag tekstur, aby wyłapać nieprzezroczyste
if (iAlpha & iFlags & 0x1F1F001F) // czy w ogóle jest co robić w tym cyklu?
{
TSubModel::fSquareDist = fSquareDistance; // zmienna globalna!
if (StartVBO())
{ // odwrócenie flag, aby wyłapać nieprzezroczyste
Root->ReplacableSet(ReplacableSkinId, iAlpha);
Root->pRoot = this;
float mv[16], p[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, p);
World.shader.set_mv(glm::make_mat4(mv));
World.shader.set_p(glm::make_mat4(p));
Root->RenderVBO(glm::make_mat4(mv));
EndVBO();
}
}
};
void TModel3d::RaRenderAlpha(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
{ // renderowanie specjalne, np. kabiny
if (iAlpha & iFlags & 0x2F2F002F) // czy w ogóle jest co robić w tym cyklu?
{
TSubModel::fSquareDist = fSquareDistance; // zmienna globalna!
if (StartVBO())
{
Root->ReplacableSet(ReplacableSkinId, iAlpha);
float mv[16], p[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, p);
World.shader.set_mv(glm::make_mat4(mv));
World.shader.set_p(glm::make_mat4(p));
Root->RenderAlphaVBO(glm::make_mat4(mv));
EndVBO();
}
}
};
#endif
//-----------------------------------------------------------------------------
// 2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów
//-----------------------------------------------------------------------------
#ifdef EU07_USE_OLD_RENDERCODE
void TModel3d::Render(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type *ReplacableSkinId, int iAlpha)
{ // nieprzezroczyste, Display List
glPushMatrix();
glTranslated(vPosition->x, vPosition->y, vPosition->z);
if (vAngle->y != 0.0)
glRotated(vAngle->y, 0.0, 1.0, 0.0);
if (vAngle->x != 0.0)
glRotated(vAngle->x, 1.0, 0.0, 0.0);
if (vAngle->z != 0.0)
glRotated(vAngle->z, 0.0, 0.0, 1.0);
TSubModel::fSquareDist =
SquareMagnitude(*vPosition - Global::GetCameraPosition()); // zmienna globalna!
// odwrócenie flag, aby wyłapać nieprzezroczyste
Root->ReplacableSet(ReplacableSkinId, iAlpha ^ 0x0F0F000F);
Root->RenderDL();
glPopMatrix();
};
void TModel3d::RenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type *ReplacableSkinId,
int iAlpha)
{ // przezroczyste, Display List
glPushMatrix();
glTranslated(vPosition->x, vPosition->y, vPosition->z);
if (vAngle->y != 0.0)
glRotated(vAngle->y, 0.0, 1.0, 0.0);
if (vAngle->x != 0.0)
glRotated(vAngle->x, 1.0, 0.0, 0.0);
if (vAngle->z != 0.0)
glRotated(vAngle->z, 0.0, 0.0, 1.0);
TSubModel::fSquareDist =
SquareMagnitude(*vPosition - Global::GetCameraPosition()); // zmienna globalna!
Root->ReplacableSet(ReplacableSkinId, iAlpha);
Root->RenderAlphaDL();
glPopMatrix();
};
void TModel3d::RaRender(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId, int iAlpha)
{ // nieprzezroczyste, VBO
glPushMatrix();
glTranslated(vPosition->x, vPosition->y, vPosition->z);
if (vAngle->y != 0.0)
glRotated(vAngle->y, 0.0, 1.0, 0.0);
if (vAngle->x != 0.0)
glRotated(vAngle->x, 1.0, 0.0, 0.0);
if (vAngle->z != 0.0)
glRotated(vAngle->z, 0.0, 0.0, 1.0);
TSubModel::fSquareDist =
SquareMagnitude(*vPosition - Global::GetCameraPosition()); // zmienna globalna!
if (StartVBO())
{ // odwrócenie flag, aby wyłapać nieprzezroczyste
Root->ReplacableSet(ReplacableSkinId, iAlpha ^ 0x0F0F000F);
float mv[16], p[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, p);
World.shader.set_mv(glm::make_mat4(mv));
World.shader.set_p(glm::make_mat4(p));
Root->RenderVBO(glm::make_mat4(mv));
EndVBO();
}
glPopMatrix();
};
void TModel3d::RaRenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId,
int iAlpha)
{ // przezroczyste, VBO
glPushMatrix();
glTranslated(vPosition->x, vPosition->y, vPosition->z);
if (vAngle->y != 0.0)
glRotated(vAngle->y, 0.0, 1.0, 0.0);
if (vAngle->x != 0.0)
glRotated(vAngle->x, 1.0, 0.0, 0.0);
if (vAngle->z != 0.0)
glRotated(vAngle->z, 0.0, 0.0, 1.0);
TSubModel::fSquareDist =
SquareMagnitude(*vPosition - Global::GetCameraPosition()); // zmienna globalna!
if (StartVBO())
{
Root->ReplacableSet(ReplacableSkinId, iAlpha);
float mv[16], p[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, p);
World.shader.set_mv(glm::make_mat4(mv));
World.shader.set_p(glm::make_mat4(p));
Root->RenderAlphaVBO(glm::make_mat4(mv));
EndVBO();
}
glPopMatrix();
};
#endif
//-----------------------------------------------------------------------------
// 2012-02 funkcje do tworzenia terenu z E3D
//-----------------------------------------------------------------------------
@@ -2232,7 +1755,7 @@ TSubModel *TModel3d::TerrainSquare(int n)
void TModel3d::TerrainRenderVBO(int n)
{ // renderowanie terenu z VBO
glPushMatrix();
::glTranslated( -Global::pCameraPosition.x, -Global::pCameraPosition.y, -Global::pCameraPosition.z );
float mv[16], p[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, p);

View File

@@ -255,12 +255,6 @@ public:
void SetRotateIK1(float3 vNewAngles);
TSubModel * GetFromName(std::string const &search, bool i = true);
TSubModel * GetFromName(char const *search, bool i = true);
#ifdef EU07_USE_OLD_RENDERCODE
void RenderDL();
void RenderAlphaDL();
void RenderVBO();
void RenderAlphaVBO();
#endif
// inline matrix4x4* GetMatrix() {return dMatrix;};
inline float4x4 * GetMatrix()
{
@@ -361,20 +355,6 @@ public:
bool LoadFromFile(std::string const &FileName, bool dynamic);
void SaveToBinFile(char const *FileName);
void BreakHierarhy();
// renderowanie specjalne
#ifdef EU07_USE_OLD_RENDERCODE
void Render(double fSquareDistance, texture_manager::size_type *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
void RenderAlpha(double fSquareDistance, texture_manager::size_type *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
#endif
void RaRender(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
void RaRenderAlpha(double fSquareDistance, texture_manager::size_type const *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
// trzy kąty obrotu
#ifdef EU07_USE_OLD_RENDERCODE
void Render( vector3 *vPosition, vector3 *vAngle, texture_manager::size_type *ReplacableSkinId = NULL, int iAlpha = 0x30300030 );
void RenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
#endif
void RaRender(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
void RaRenderAlpha(vector3 *vPosition, vector3 *vAngle, texture_manager::size_type const *ReplacableSkinId = NULL, int iAlpha = 0x30300030);
// inline int GetSubModelsCount() { return (SubModelsCount); };
int Flags() const
{

View File

@@ -40,7 +40,7 @@ void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation,
bool Dynamic, bool freqmod, double rmin)
{
// Nazwa=SoundName; //to tak raczej nie zadziała, (SoundName) jest tymczasowe
pSound = TSoundsManager::GetFromName(SoundName.c_str(), Dynamic, &fFrequency);
pSound = TSoundsManager::GetFromName(SoundName, Dynamic, &fFrequency);
if (pSound)
{
if (freqmod)
@@ -48,8 +48,7 @@ void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation,
{ // dla modulowanych nie może być zmiany mnożnika, bo częstotliwość w nagłówku byłą
// ignorowana, a mogła być inna niż 22050
fFrequency = 22050.0;
ErrorLog("Bad sound: " + std::string(SoundName) +
", as modulated, should have 22.05kHz in header");
ErrorLog("Bad sound: " + SoundName + ", as modulated, should have 22.05kHz in header");
}
AM = 1.0;
pSound->SetVolume(DSBVOLUME_MIN);
@@ -57,7 +56,7 @@ void TRealSound::Init(std::string const &SoundName, double DistanceAttenuation,
else
{ // nie ma dźwięku, to jest wysyp
AM = 0;
ErrorLog("Missed sound: " + std::string(SoundName));
ErrorLog("Missed sound: " + SoundName);
}
if (DistanceAttenuation > 0.0)
{
@@ -268,26 +267,8 @@ void TTextSound::Play(double Volume, int Looping, bool ListenerInside, vector3 N
{ // jeśli ma powiązany tekst
DWORD stat;
pSound->GetStatus(&stat);
if (!(stat & DSBSTATUS_PLAYING)) // jeśli nie jest aktualnie odgrywany
{
/*
std::string t( asText );
size_t i;
do
{ // na razie zrobione jakkolwiek, docelowo przenieść teksty do tablicy nazw
i = t.find('\r'); // znak nowej linii
if( i == std::string::npos ) {
Global::tranTexts.Add( t, fTime, true );
}
else
{
Global::tranTexts.Add(t.substr(0, i), fTime, true);
t.erase(0, i + 1);
while (t.empty() ? false : (unsigned char)(t[1]) < 33)
t.erase(0, 1);
}
} while (i != std::string::npos);
*/
if (!(stat & DSBSTATUS_PLAYING)) {
// jeśli nie jest aktualnie odgrywany
Global::tranTexts.Add( asText, fTime, true );
}
}

View File

@@ -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);
@@ -120,29 +114,30 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
{
ErrorLog( "Bad geometry (zero length) for spline \"" + pOwner->NameGet() + "\" at " + Where( Point1 ) );
// MessageBox(0,"Length<=0","TSegment::Init",MB_OK);
fLength = 0.01; // crude workaround TODO: fix this properly
/*
return false; // zerowe nie mogą być
*/
}
fStoop = atan2((Point2.y - Point1.y),
fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
if( ( pOwner->eType == tt_Switch )
&& ( fStep * 3.0 > fLength ) ) {
// NOTE: a workaround for too short switches (less than 3 segments) messing up animation/generation of blades
fStep = fLength / 3.0;
}
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
// fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
fTsBuffer = new double[ iSegCount + 1 ];
fTsBuffer[ 0 ] = 0; /* TODO : fix fTsBuffer */
while( s < fLength ) {
i++;
s += fStep;
if( s > fLength )
s = fLength;
fTsBuffer[ i ] = GetTFromS( s );
}
}
iSegCount = static_cast<int>( std::ceil( fLength / fStep ) ); // potrzebne do VBO
fStep = fLength / iSegCount; // update step to equalize size of individual pieces
fTsBuffer = new double[ iSegCount + 1 ];
fTsBuffer[ 0 ] = 0.0;
for( int i = 1; i < iSegCount; ++i ) {
fTsBuffer[ i ] = GetTFromS( i * fStep );
}
fTsBuffer[ iSegCount ] = 1.0;
return true;
}
@@ -324,410 +319,203 @@ 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)
int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, 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
int vertexcount{ 0 };
if( !fTsBuffer )
return vertexcount; // 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);
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( 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;
pt -= Origin;
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
::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;
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;
}
++vertexcount;
}
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;
pt -= Origin;
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
::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;
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;
}
++vertexcount;
}
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++)
{
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);
}
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 ) {
if( bRender ) {
for( int j = 0; j < iNumShapePoints; ++j ) {
//łuk z jednym profilem
pt = parallel1 * ( ShapePoints[ j ].x - fOffsetX ) + pos1;
pt.y += ShapePoints[ j ].y;
pt -= Origin;
norm = ShapePoints[ j ].n.x * parallel1;
norm.y += ShapePoints[ j ].n.y;
if( Output == nullptr ) {
// immediate mode
::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;
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv1;
++Output;
}
++vertexcount;
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);
pt = parallel2 * ShapePoints[ j ].x + pos2;
pt.y += ShapePoints[ j ].y;
pt -= Origin;
norm = ShapePoints[ j ].n.x * parallel2;
norm.y += ShapePoints[ j ].n.y;
if( Output == nullptr ) {
// immediate mode
::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;
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv2;
++Output;
}
++vertexcount;
}
}
}
if( Output == nullptr ) {
// immediate mode
glEnd();
pos1 = pos2;
parallel1 = parallel2;
tv1 = tv2;
a1 = a2;
}
pos1 = pos2;
parallel1 = parallel2;
tv1 = tv2;
}
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;
tv1 = tv2;
a1 = a2;
}
}
return vertexcount;
};
void TSegment::Render()
@@ -778,300 +566,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
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++;
}
}
};
//---------------------------------------------------------------------------

View File

@@ -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);
int RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, vector3 **p = nullptr, bool bRender = true);
void Render();
inline double GetLength()
{
@@ -145,15 +135,10 @@ class TSegment
return 1;
return iSegCount;
};
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
};
//---------------------------------------------------------------------------

116
Sound.cpp
View File

@@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "Usefull.h"
#include "mczapkie/mctools.h"
#include "WavRead.h"
//#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) \
{ \
if (p) \
@@ -24,43 +24,31 @@ http://mozilla.org/MPL/2.0/.
} \
}
char Directory[] = "sounds\\";
LPDIRECTSOUND TSoundsManager::pDS;
LPDIRECTSOUNDNOTIFY TSoundsManager::pDSNotify;
int TSoundsManager::Count = 0;
TSoundContainer *TSoundsManager::First = NULL;
TSoundContainer::TSoundContainer(LPDIRECTSOUND pDS, const char *Directory, const char *strFileName,
int NConcurrent)
TSoundContainer::TSoundContainer(LPDIRECTSOUND pDS, std::string const &Directory, std::string const &Filename, int NConcurrent)
{ // wczytanie pliku dźwiękowego
int hr = 111;
DSBuffer = NULL; // na początek, gdyby uruchomić dźwięków się nie udało
DSBuffer = nullptr; // na początek, gdyby uruchomić dźwięków się nie udało
Concurrent = NConcurrent;
Oldest = 0;
// strcpy(Name, strFileName);
strcpy(Name, Directory);
strcat(Name, strFileName);
CWaveSoundRead *pWaveSoundRead;
m_name = Directory + Filename;
// Create a new wave file class
pWaveSoundRead = new CWaveSoundRead();
std::shared_ptr<CWaveSoundRead> pWaveSoundRead = std::make_shared<CWaveSoundRead>();
// Load the wave file
if (FAILED(pWaveSoundRead->Open(Name)))
if (FAILED(pWaveSoundRead->Open(strdup(strFileName))))
{
// SetFileUI( hDlg, TEXT("Bad wave file.") );
ErrorLog( "Missed sound: " + std::string( strFileName ) );
return;
}
if( ( FAILED( pWaveSoundRead->Open( m_name ) ) )
&& ( FAILED( pWaveSoundRead->Open( Filename ) ) ) ) {
ErrorLog( "Missed sound: " + Filename );
return;
}
strcpy(Name, ToLower(strFileName).c_str());
m_name = ToLower( Filename );
// Set up the direct sound buffer, and only request the flags needed
// since each requires some overhead and limits if the buffer can
@@ -133,27 +121,10 @@ TSoundContainer::TSoundContainer(LPDIRECTSOUND pDS, const char *Directory, const
// We dont need the wav file data buffer anymore, so delete it
delete[] pbWavData;
delete pWaveSoundRead;
DSBuffers.push(DSBuffer);
/*
for (int i=1; i<Concurrent; i++)
{
if( FAILED( hr= pDS->DuplicateSoundBuffer(pDSBuffer[0],&(pDSBuffer[i]))))
{
Concurrent= i;
break;
};
};*/
};
TSoundContainer::~TSoundContainer()
{
// for (int i=Concurrent-1; i>=0; i--)
// SAFE_RELEASE( pDSBuffer[i] );
// free(pDSBuffer);
while (!DSBuffers.empty())
{
SAFE_RELEASE(DSBuffers.top());
@@ -185,84 +156,51 @@ void TSoundsManager::Free()
SAFE_RELEASE(pDS);
};
TSoundContainer * TSoundsManager::LoadFromFile(const char *Dir, const char *Name, int Concurrent)
TSoundContainer * TSoundsManager::LoadFromFile( std::string const &Dir, std::string const &Filename, int Concurrent)
{
TSoundContainer *Tmp = First;
First = new TSoundContainer(pDS, Dir, Name, Concurrent);
First->Next = Tmp;
TSoundContainer *tmp = First;
First = new TSoundContainer(pDS, Dir, Filename, Concurrent);
First->Next = tmp;
Count++;
return First; // albo NULL, jak nie wyjdzie (na razie zawsze wychodzi)
};
void TSoundsManager::LoadSounds(char *Directory)
{ // wczytanie wszystkich plików z katalogu - mało elastyczne
WIN32_FIND_DATA FindFileData;
HANDLE handle = FindFirstFile("sounds\\*.wav", &FindFileData);
if (handle != INVALID_HANDLE_VALUE)
do
{
LoadFromFile(Directory, FindFileData.cFileName, 1);
} while (FindNextFile(handle, &FindFileData));
FindClose(handle);
};
LPDIRECTSOUNDBUFFER TSoundsManager::GetFromName(const char *Name, bool Dynamic, float *fSamplingRate)
LPDIRECTSOUNDBUFFER TSoundsManager::GetFromName(std::string const &Name, bool Dynamic, float *fSamplingRate)
{ // wyszukanie dźwięku w pamięci albo wczytanie z pliku
std::string name{ ToLower(Name) };
std::string file;
if (Dynamic)
{ // próba wczytania z katalogu pojazdu
file = Global::asCurrentDynamicPath + Name;
file = Global::asCurrentDynamicPath + name;
if (FileExists(file))
Name = file.c_str(); // nowa nazwa
name = file; // nowa nazwa
else
Dynamic = false; // wczytanie z "sounds/"
}
TSoundContainer *Next = First;
for (int i = 0; i < Count; i++)
{
if (strcmp(Name, Next->Name) == 0)
{
if( name == Next->m_name ) {
if (fSamplingRate)
*fSamplingRate = Next->fSamplingRate; // częstotliwość
return (Next->GetUnique(pDS));
// DSBuffers.
/*
Next->pDSBuffer[Next->Oldest]->Stop();
Next->pDSBuffer[Next->Oldest]->SetCurrentPosition(0);
if (Next->Oldest<Next->Concurrent-1)
{
Next->Oldest++;
return (Next->pDSBuffer[Next->Oldest-1]);
}
else
{
Next->Oldest= 0;
return (Next->pDSBuffer[Next->Concurrent-1]);
};
/* for (int j=0; j<Next->Concurrent; j++)
{
Next->pDSBuffer[j]->GetStatus(&dwStatus);
if ((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
return (Next->pDSBuffer[j]);
} */
}
else
Next = Next->Next;
};
if (Dynamic) // wczytanie z katalogu pojazdu
Next = LoadFromFile("", Name, 1);
Next = LoadFromFile("", name, 1);
else
Next = LoadFromFile(Directory, Name, 1);
Next = LoadFromFile(szSoundPath, name, 1);
if (Next)
{ //
if (fSamplingRate)
*fSamplingRate = Next->fSamplingRate; // częstotliwość
return Next->GetUnique(pDS);
}
ErrorLog("Missed sound: " + std::string(Name) );
return (NULL);
ErrorLog("Missed sound: " + Name );
return (nullptr);
};
void TSoundsManager::RestoreAll()
@@ -299,10 +237,6 @@ void TSoundsManager::RestoreAll()
};
};
// void TSoundsManager::Init(char *Name, int Concurrent)
// TSoundsManager::TSoundsManager(HWND hWnd)
// void TSoundsManager::Init(HWND hWnd, char *NDirectory)
void TSoundsManager::Init(HWND hWnd)
{

38
Sound.h
View File

@@ -7,56 +7,44 @@ obtain one at
http://mozilla.org/MPL/2.0/.
*/
#ifndef SoundH
#define SoundH
#pragma once
#include <stack>
#include <dsound.h>
typedef LPDIRECTSOUNDBUFFER PSound;
// inline Playing(PSound Sound)
//{
//}
class TSoundContainer
{
public:
public:
int Concurrent;
int Oldest;
char Name[80];
std::string m_name;
LPDIRECTSOUNDBUFFER DSBuffer;
float fSamplingRate; // częstotliwość odczytana z pliku
int iBitsPerSample; // ile bitów na próbkę
TSoundContainer *Next;
std::stack<LPDIRECTSOUNDBUFFER> DSBuffers;
LPDIRECTSOUNDBUFFER GetUnique(LPDIRECTSOUND pDS);
TSoundContainer(LPDIRECTSOUND pDS, const char *Directory, const char *strFileName, int NConcurrent);
TSoundContainer(LPDIRECTSOUND pDS, std::string const &Directory, std::string const &Filename, int NConcurrent);
~TSoundContainer();
LPDIRECTSOUNDBUFFER GetUnique( LPDIRECTSOUND pDS );
};
class TSoundsManager
{
private:
private:
static LPDIRECTSOUND pDS;
static LPDIRECTSOUNDNOTIFY pDSNotify;
// static char Directory[80];
static int Count;
static TSoundContainer *First;
static TSoundContainer * LoadFromFile(const char *Dir, const char *Name, int Concurrent);
static int Count;
public:
// TSoundsManager(HWND hWnd);
// static void Init(HWND hWnd, char *NDirectory);
static void Init(HWND hWnd);
static TSoundContainer * LoadFromFile( std::string const &Directory, std::string const &FileName, int Concurrent);
public:
~TSoundsManager();
static void Init( HWND hWnd );
static void Free();
static void Init(char *Name, int Concurrent);
static void LoadSounds(char *Directory);
static LPDIRECTSOUNDBUFFER GetFromName(const char *Name, bool Dynamic, float *fSamplingRate = NULL);
static LPDIRECTSOUNDBUFFER GetFromName( std::string const &Name, bool Dynamic, float *fSamplingRate = NULL );
static void RestoreAll();
};
//---------------------------------------------------------------------------
#endif

View File

@@ -424,7 +424,6 @@ opengl_texture::load_TGA() {
else if( tgaheader[ 2 ] == 10 ) {
// compressed TGA
int currentpixel = 0;
int currentbyte = 0;
unsigned char buffer[ 4 ] = { 255, 255, 255, 255 };
const int pixelcount = data_width * data_height;

1748
Track.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -240,7 +240,7 @@ class TTrack : public Resource
void Render(); // renderowanie z Display Lists
int RaArrayPrepare(); // zliczanie rozmiaru dla VBO sektroa
void RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start); // wypełnianie VBO
void RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int const Vertexcount); // wypełnianie VBO
void RaRenderVBO(int iPtr); // renderowanie z VBO sektora
void RenderDyn(); // renderowanie nieprzezroczystych pojazdów (oba tryby)
void RenderDynAlpha(); // renderowanie przezroczystych pojazdów (oba tryby)
@@ -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)

View File

@@ -108,9 +108,160 @@ TTraction::~TTraction()
}
void TTraction::Optimize()
void TTraction::Optimize( Math3D::vector3 const &Origin )
{
if (Wires != 0)
{
// Dlugosc odcinka trakcji 'Winger
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 - Origin.x,
pPoint1.y - Origin.y,
pPoint1.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z);
glVertex3f(
pPoint2.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x,
pPoint2.y - Origin.y,
pPoint2.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z );
glEnd();
// Nie wiem co 'Marcin
Math3D::vector3 pt1, pt2, pt3, pt4, v1, v2;
v1 = pPoint4 - pPoint3;
v2 = pPoint2 - pPoint1;
float step = 0;
if (iNumSections > 0)
step = 1.0f / (float)iNumSections;
float f = step;
float mid = 0.5;
float t;
// Przewod nosny 'Marcin
if (Wires > 1)
{
glBegin(GL_LINE_STRIP);
glVertex3f(
pPoint3.x - Origin.x,
pPoint3.y - Origin.y,
pPoint3.z - Origin.z );
for (int i = 0; i < iNumSections - 1; ++i)
{
pt3 = pPoint3 + v1 * f;
t = (1 - std::fabs(f - mid) * 2);
if ((Wires < 4) || ((i != 0) && (i != iNumSections - 2)))
glVertex3f(
pt3.x - Origin.x,
pt3.y - std::sqrt(t) * fHeightDifference - Origin.y,
pt3.z - Origin.z );
f += step;
}
glVertex3f(
pPoint4.x - Origin.x,
pPoint4.y - Origin.y,
pPoint4.z - Origin.z );
glEnd();
}
// Drugi przewod jezdny 'Winger
if (Wires > 2)
{
glBegin(GL_LINE_STRIP);
glVertex3f(
pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x,
pPoint1.y - Origin.y,
pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z );
glVertex3f(
pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x,
pPoint2.y - Origin.y,
pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z );
glEnd();
}
f = step;
if (Wires == 4)
{
glBegin(GL_LINE_STRIP);
glVertex3f(
pPoint3.x - Origin.x,
pPoint3.y - 0.65f * fHeightDifference - Origin.y,
pPoint3.z - Origin.z );
for (int i = 0; i < iNumSections - 1; ++i)
{
pt3 = pPoint3 + v1 * f;
t = (1 - std::fabs(f - mid) * 2);
glVertex3f(
pt3.x - Origin.x,
pt3.y - std::sqrt( t ) * fHeightDifference - (
( ( i == 0 )
|| ( i == iNumSections - 2 ) ) ?
0.25f * fHeightDifference :
0.05 )
- Origin.y,
pt3.z - Origin.z );
f += step;
}
glVertex3f(
pPoint4.x - Origin.x,
pPoint4.y - 0.65f * fHeightDifference - Origin.y,
pPoint4.z - Origin.z );
glEnd();
}
f = step;
// Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
if (Wires != 1)
{
glBegin(GL_LINES);
for (int i = 0; i < iNumSections - 1; ++i)
{
float flo, flo1;
flo = (Wires == 4 ? 0.25f * fHeightDifference : 0);
flo1 = (Wires == 4 ? +0.05 : 0);
pt3 = pPoint3 + v1 * f;
pt4 = pPoint1 + v2 * f;
t = (1 - std::fabs(f - mid) * 2);
if ((i % 2) == 0)
{
glVertex3f(
pt3.x - Origin.x,
pt3.y - std::sqrt(t) * fHeightDifference - ((i == 0) || (i == iNumSections - 2) ? flo : flo1) - Origin.y,
pt3.z - Origin.z );
glVertex3f(
pt4.x - (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x,
pt4.y - Origin.y,
pt4.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z );
}
else
{
glVertex3f(
pt3.x - Origin.x,
pt3.y - std::sqrt(t) * fHeightDifference - ((i == 0) || (i == iNumSections - 2) ? flo : flo1) - Origin.y,
pt3.z - Origin.z );
glVertex3f(
pt4.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x,
pt4.y - Origin.y,
pt4.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z );
}
if ((Wires == 4) && ((i == 1) || (i == iNumSections - 3)))
{
glVertex3f(
pt3.x - Origin.x,
pt3.y - std::sqrt(t) * fHeightDifference - 0.05 - Origin.y,
pt3.z - Origin.z );
glVertex3f(
pt3.x - Origin.x,
pt3.y - std::sqrt(t) * fHeightDifference - Origin.y,
pt3.z - Origin.z );
}
f += step;
}
glEnd();
}
glEndList();
}
}
/*
void TTraction::InitCenter(vector3 Angles, vector3 pOrigin)
@@ -119,149 +270,96 @@ void TTraction::InitCenter(vector3 Angles, vector3 pOrigin)
fSquaredRadius= SquareMagnitude((pPoint2-pPoint1)*0.5f);
} */
void TTraction::RenderDL(float mgn) // McZapkie: mgn to odleglosc od obserwatora
void TTraction::RenderDL(float mgn, Math3D::vector3 const &Origin ) // 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.x; // w zaleźności od koloru swiatła
g *= Global::daylight.ambient.y;
b *= Global::daylight.ambient.z;
#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ą
Optimize( Origin ); // generowanie DL w miarę potrzeby
::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)
int TTraction::RaArrayFill(CVertNormTex *Vert, Math3D::vector3 const &Origin)
{ // wypełnianie tablic VBO
CVertNormTex *old = Vert;
double ddp = hypot(pPoint2.x - pPoint1.x, pPoint2.z - pPoint1.z);
int debugvertexcount{ 0 };
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->y = pPoint1.y;
Vert->z = pPoint1.z - (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
Vert->x = pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pPoint1.y - Origin.y;
Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
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;
++debugvertexcount;
Vert->x = pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pPoint2.y - Origin.y;
Vert->z = pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
// 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;
@@ -269,159 +367,197 @@ void TTraction::RaArrayFill(CVertNormTex *Vert)
// Przewod nosny 'Marcin
if (Wires > 1)
{ // lina nośna w kawałkach
Vert->x = pPoint3.x;
Vert->y = pPoint3.y;
Vert->z = pPoint3.z;
Vert->x = pPoint3.x - Origin.x;
Vert->y = pPoint3.y - Origin.y;
Vert->z = pPoint3.z - Origin.z;
++Vert;
for (int i = 0; i < iNumSections - 1; i++)
++debugvertexcount;
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 - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
}
f += step;
}
Vert->x = pPoint4.x;
Vert->y = pPoint4.y;
Vert->z = pPoint4.z;
Vert->x = pPoint4.x - Origin.x;
Vert->y = pPoint4.y - Origin.y;
Vert->z = pPoint4.z - Origin.z;
++Vert;
++debugvertexcount;
}
// 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;
Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
Vert->x = pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x;
Vert->y = pPoint1.y - Origin.y;
Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z;
++Vert;
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;
++debugvertexcount;
Vert->x = pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x;
Vert->y = pPoint2.y - Origin.y;
Vert->z = pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
}
f = step;
if( Wires == 4 ) {
Vert->x = pPoint3.x - Origin.x;
Vert->y = pPoint3.y - 0.65f * fHeightDifference - Origin.y;
Vert->z = pPoint3.z - Origin.z;
++Vert;
++debugvertexcount;
for( int i = 0; i < iNumSections - 1; ++i ) {
pt3 = pPoint3 + v1 * f;
t = ( 1 - std::fabs( f - mid ) * 2 );
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - (
( ( i == 0 )
|| ( i == iNumSections - 2 ) ) ?
0.25f * fHeightDifference :
0.05 )
- Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
f += step;
}
Vert->x = pPoint4.x - Origin.x;
Vert->y = pPoint4.y - 0.65f * fHeightDifference - Origin.y;
Vert->z = pPoint4.z - Origin.z;
++Vert;
++debugvertexcount;
}
f = step;
// Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
if (Wires > 1)
{
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);
Vert->x = pt3.x;
Vert->y = pt3.y - sqrt(t) * fHeightDifference;
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;
t = (1 - std::fabs(f - mid) * 2);
if( ( i % 2 ) == 0 ) {
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pt4.y - Origin.y;
Vert->z = pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
}
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;
else {
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pt4.y - Origin.y;
Vert->z = pt4.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
}
if( ( ( Wires == 4 )
&& ( ( i == 1 )
|| ( i == iNumSections - 3 ) ) ) ) {
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05 - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
}
++Vert;
f += step;
}
}
if ((Vert - old) != iLines)
WriteLog("!!! Wygenerowano punktów " + std::to_string(Vert - old) + ", powinno być " +
std::to_string(iLines));
return debugvertexcount;
};
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.x; // w zaleźności od koloru swiatła
g *= Global::daylight.ambient.y;
b *= Global::daylight.ambient.z;
#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);
}
};
@@ -492,11 +628,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ć
{
@@ -504,6 +645,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
@@ -589,3 +743,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.x;
Green *= Global::daylight.ambient.y;
Blue *= Global::daylight.ambient.z;
}
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;
}
}
}

View File

@@ -54,10 +54,9 @@ 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();
void Optimize( Math3D::vector3 const &Origin );
TTraction();
~TTraction();
@@ -67,9 +66,9 @@ class TTraction
// { return TNode::Hit(x,z,hitPoint,hitDirection); };
// virtual bool Move(double dx, double dy, double dz) { return false; };
// virtual void SelectedRender();
void RenderDL(float mgn);
void RenderDL(float mgn, Math3D::vector3 const &Origin );
int RaArrayPrepare();
void RaArrayFill(CVertNormTex *Vert);
int RaArrayFill( CVertNormTex *Vert, Math3D::vector3 const &Origin );
void RenderVBO(float mgn, int iPtr);
int TestPoint(Math3D::vector3 *Point);
void Connect(int my, TTraction *with, int to);
@@ -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;
};
//---------------------------------------------------------------------------

896
Train.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -146,8 +146,10 @@ class TTrain
static void OnCommand_pantographlowerall( TTrain *Train, command_data const &Command );
static void OnCommand_linebreakertoggle( TTrain *Train, command_data const &Command );
static void OnCommand_convertertoggle( TTrain *Train, command_data const &Command );
static void OnCommand_convertertogglelocal( TTrain *Train, command_data const &Command );
static void OnCommand_converteroverloadrelayreset( TTrain *Train, command_data const &Command );
static void OnCommand_compressortoggle( TTrain *Train, command_data const &Command );
static void OnCommand_compressortogglelocal( TTrain *Train, command_data const &Command );
static void OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command );
static void OnCommand_motordisconnect( TTrain *Train, command_data const &Command );
static void OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command_data const &Command );
@@ -251,7 +253,9 @@ public: // reszta może by?publiczna
TGauge ggIgnitionKey;
TGauge ggCompressorButton;
TGauge ggCompressorLocalButton; // controls only compressor of its own unit (et42-specific)
TGauge ggConverterButton;
TGauge ggConverterLocalButton; // controls only converter of its own unit (et42-specific)
TGauge ggConverterOffButton;
// ABu 090305 - syrena i prad nastepnego czlonu
@@ -484,6 +488,7 @@ public: // reszta może by?publiczna
public:
float fPress[20][3]; // cisnienia dla wszystkich czlonow
static std::vector<std::string> const fPress_labels;
float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych
int RadioChannel() { return iRadioChannel; };
inline TDynamicObject *Dynamic() { return DynamicObject; };

12
VBO.cpp
View File

@@ -45,7 +45,9 @@ void CVertNormTex::serialize(std::ostream &s)
CMesh::CMesh()
{ // utworzenie pustego obiektu
#ifdef EU07_USE_OLD_VERTEXBUFFER
m_pVNT = nullptr;
#endif
m_nVertexCount = -1;
m_nVBOVertices = 0; // nie zarezerwowane
};
@@ -58,7 +60,13 @@ CMesh::~CMesh()
void CMesh::MakeArray(int n)
{ // tworzenie tablic
m_nVertexCount = n;
#ifdef EU07_USE_OLD_VERTEXBUFFER
assert( m_pVNT == nullptr );
m_pVNT = new CVertNormTex[m_nVertexCount]; // przydzielenie pamięci dla tablicy
#else
m_pVNT.clear();
m_pVNT.resize( m_nVertexCount );
#endif
};
void CMesh::BuildVBOs(bool del)
@@ -91,7 +99,11 @@ void CMesh::Clear()
}
m_nVBOVertices = 0;
m_nVertexCount = -1; // do ponownego zliczenia
#ifdef EU07_USE_OLD_VERTEXBUFFER
SafeDeleteArray(m_pVNT); // usuwanie tablic, gdy były użyte do Vertex Array
#else
m_pVNT.clear();
#endif
};
extern TWorld World;

7
VBO.h
View File

@@ -11,6 +11,9 @@ http://mozilla.org/MPL/2.0/.
#ifndef VBOH
#define VBOH
#define EU07_USE_OLD_VERTEXBUFFER
//---------------------------------------------------------------------------
class CVertNormTex
{
@@ -34,7 +37,11 @@ class CMesh
gl_program shader;
public:
int m_nVertexCount; // liczba wierzchołków
#ifdef EU07_USE_OLD_VERTEXBUFFER
CVertNormTex *m_pVNT;
#else
std::vector<CVertNormTex> m_pVNT;
#endif
unsigned int m_nVBOVertices; // numer VBO z wierzchołkami
CMesh();
~CMesh();

808
World.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -47,8 +47,10 @@ commanddescription_sequence Commands_descriptions = {
{ "reverserdecrease", command_target::vehicle },
{ "linebreakertoggle", command_target::vehicle },
{ "convertertoggle", command_target::vehicle },
{ "convertertogglelocal", command_target::vehicle },
{ "converteroverloadrelayreset", command_target::vehicle },
{ "compressortoggle", command_target::vehicle },
{ "compressortogglelocal", command_target::vehicle },
{ "motoroverloadrelaythresholdtoggle", command_target::vehicle },
{ "motoroverloadrelayreset", command_target::vehicle },
{ "notchingrelaytoggle", command_target::vehicle },

View File

@@ -42,8 +42,10 @@ enum class user_command {
reverserdecrease,
linebreakertoggle,
convertertoggle,
convertertogglelocal,
converteroverloadrelayreset,
compressortoggle,
compressortogglelocal,
motoroverloadrelaythresholdtoggle,
motoroverloadrelayreset,
notchingrelaytoggle,

View File

@@ -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)

View File

@@ -27,6 +27,9 @@ public:
calculate(glm::mat4 const &Projection, glm::mat4 const &Modelview);
// returns true if specified point is inside of the frustum
inline
bool
point_inside( glm::vec3 const &Point ) const { return point_inside( Point.x, Point.y, Point.z ); }
inline
bool
point_inside( float3 const &Point ) const { return point_inside( Point.x, Point.y, Point.z ); }
inline
@@ -36,6 +39,9 @@ public:
point_inside( float const X, float const Y, float const Z ) const;
// tests if the sphere is in frustum, returns the distance between origin and sphere centre
inline
float
sphere_inside( glm::vec3 const &Center, float const Radius ) const { return sphere_inside( Center.x, Center.y, Center.z, Radius ); }
inline
float
sphere_inside( float3 const &Center, float const Radius ) const { return sphere_inside( Center.x, Center.y, Center.z, Radius ); }
inline
@@ -45,6 +51,9 @@ public:
sphere_inside( float const X, float const Y, float const Z, float const Radius ) const;
// returns true if specified cube is inside of the frustum. Size = half of the length
inline
bool
cube_inside( glm::vec3 const &Center, float const Size ) const { return cube_inside( Center.x, Center.y, Center.z, Size ); }
inline
bool
cube_inside( float3 const &Center, float const Size ) const { return cube_inside( Center.x, Center.y, Center.z, Size ); }
inline

View File

@@ -80,7 +80,7 @@ private:
glm::vec2 m_leftstick;
glm::vec2 m_rightstick;
glm::vec2 m_triggers;
double m_modeaccumulator; // used to throttle command input rate for vehicle controls
double m_modeaccumulator{ 0.0 }; // used to throttle command input rate for vehicle controls
};
//---------------------------------------------------------------------------

View File

@@ -228,10 +228,14 @@ keyboard_input::default_bindings() {
{ GLFW_KEY_M },
// convertertoggle
{ GLFW_KEY_X },
// convertertogglelocal
{ GLFW_KEY_X | keymodifier::shift },
// converteroverloadrelayreset
{ GLFW_KEY_N | keymodifier::control },
// compressortoggle
{ GLFW_KEY_C },
// compressortoggleloal
{ GLFW_KEY_C | keymodifier::shift },
// motoroverloadrelaythresholdtoggle
{ GLFW_KEY_F },
// motoroverloadrelayreset

View File

@@ -70,7 +70,7 @@ private:
bool m_shift{ false };
bool m_ctrl{ false };
bindings_cache m_bindingscache;
std::array<char, GLFW_KEY_LAST> m_keys;
std::array<char, GLFW_KEY_LAST + 1> m_keys;
};
//---------------------------------------------------------------------------

View File

@@ -82,9 +82,9 @@ typedef std::vector<opengl_stack> openglstack_array;
public:
// constructors:
opengl_matrices() {
m_stacks.emplace_back(); // projection
m_stacks.emplace_back(); // modelview
}
m_stacks.emplace_back(); // projection
m_stacks.emplace_back(); // modelview
}
// methods:
void

View File

@@ -11,8 +11,12 @@ http://mozilla.org/MPL/2.0/.
#include "renderer.h"
#include "globals.h"
#include "World.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"
@@ -32,11 +36,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 );
}
@@ -103,13 +107,19 @@ opengl_renderer::Init( GLFWwindow *Window ) {
World.shader = gl_program_light({ gl_shader("lighting.vert"), gl_shader("blinnphong.frag") });
Global::daylight.intensity = 1.0f; //m7todo: przenieść
WriteLog("Loading common gfx data...");
m_glaretextureid = GetTextureId("fx\\lightglare", szTexturePath);
m_suntextureid = GetTextureId("fx\\sun", szTexturePath);
m_moontextureid = GetTextureId("fx\\moon", szTexturePath);
WriteLog("...gfx data pre-loading done");
return true;
// preload some common textures
WriteLog( "Loading common gfx data..." );
m_glaretextureid = GetTextureId( "fx\\lightglare", szTexturePath );
m_suntextureid = GetTextureId( "fx\\sun", szTexturePath );
m_moontextureid = GetTextureId( "fx\\moon", szTexturePath );
WriteLog( "...gfx data pre-loading done" );
// prepare debug mode objects
m_quadric = gluNewQuadric();
gluQuadricNormals( m_quadric, GLU_FLAT );
return true;
}
bool
@@ -132,15 +142,22 @@ opengl_renderer::Render() {
::glLoadIdentity();
if( World.InitPerformed() ) {
/*
World.Camera.SetMatrix();
m_camera.update_frustum();
*/
glm::dmat4 worldcamera;
World.Camera.SetMatrix( worldcamera );
m_camera.update_frustum( OpenGLMatrices.data( GL_PROJECTION ), worldcamera );
// frustum tests are performed in 'world space' but after we set up frustum
// we no longer need camera translation, only rotation
::glMultMatrixd( glm::value_ptr( glm::dmat4( glm::dmat3( worldcamera ))));
glDisable(GL_FRAMEBUFFER_SRGB);
Render( &World.Environment );
glUseProgram(World.shader);
glEnable(GL_FRAMEBUFFER_SRGB);
World.Ground.Render( World.Camera.Pos );
Render( &World.Ground );
glDebug("rendering cab");
World.Render_Cab();
@@ -171,13 +188,20 @@ opengl_renderer::Render( world_environment *Environment ) {
::glDisable( GL_DEPTH_TEST );
::glDepthMask( GL_FALSE );
::glPushMatrix();
/*
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
*/
/*
glm::mat4 worldcamera;
World.Camera.SetMatrix( worldcamera );
glLoadIdentity();
glMultMatrixf( glm::value_ptr( glm::mat4( glm::mat3( worldcamera ) ) ) );
*/
// setup fog
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 ); }
@@ -230,7 +254,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 );
@@ -284,14 +308,18 @@ 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 );
::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 );
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;
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
Update_Lights( Ground->m_lights );
/*
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 );
@@ -299,34 +327,300 @@ opengl_renderer::Render( TGround *Ground ) {
for( int column = originx; column <= originx + segmentcount; ++column ) {
for( int row = originz; row <= originz + segmentcount; ++row ) {
auto &rectangle = Ground->Rects[ column ][ row ];
if( m_camera.visible( rectangle.m_area ) ) {
rectangle.RenderDL();
auto *rectangle = &Ground->Rects[ column ][ row ];
if( m_camera.visible( rectangle->m_area ) ) {
Render( rectangle );
}
}
}
*/
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
// pre-calculate camera view span
double const fieldofviewcosine =
std::cos(
std::max(
// vertical...
Global::FieldOfView / Global::ZoomFactor,
// ...or horizontal, whichever is bigger
Global::FieldOfView / Global::ZoomFactor
* std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ) ) );
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.5 )
continue; // pomijanie sektorów poza kątem patrzenia
}
// kwadrat kilometrowy nie zawsze, bo szkoda FPS
Render( &Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ] );
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::pTerrainCompact ) {
Global::pTerrainCompact->TerrainRenderVBO( TGroundRect::iFrameNumber );
}
// renderowanie nieprzezroczystych
for( i = 0; i < Ground->iRendered; ++i ) {
Render( Ground->pRendered[ i ] );
}
// regular render takes care of all solid geometry present in the scene, thus we can launch alpha parts render here
return Render_Alpha( Ground );
}
// TODO: unify ground render code, until then old version is in place
#define EU07_USE_OLD_RENDERCODE
bool
opengl_renderer::Render( TGroundRect *Groundcell ) {
::glPushMatrix();
auto const &cellorigin = Groundcell->m_area.center;
// TODO: unify all math objects
auto const originoffset = Math3D::vector3( cellorigin.x, cellorigin.y, cellorigin.z ) - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
bool result{ false }; // will be true if we do any rendering
// TODO: unify render paths
if ( Groundcell->iLastDisplay != Groundcell->iFrameNumber)
{ // tylko jezeli dany kwadrat nie był jeszcze renderowany
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
if ( Groundcell->nRenderRect && Groundcell->StartVBO())
{
for (TGroundNode *node = Groundcell->nRenderRect; node; node = node->nNext3) // następny tej grupy
#ifdef EU07_USE_OLD_RENDERCODE
node->RaRenderVBO(); // nieprzezroczyste trójkąty kwadratu kilometrowego
#else
Render( node ); // nieprzezroczyste trójkąty kwadratu kilometrowego
#endif
Groundcell->EndVBO();
Groundcell->iLastDisplay = Groundcell->iFrameNumber;
result = true;
}
if ( Groundcell->nTerrain)
Groundcell->nTerrain->smTerrain->iVisible = Groundcell->iFrameNumber; // ma się wyświetlić w tej ramce
}
::glPopMatrix();
return result;
}
#undef EU07_USE_OLD_RENDERCODE
bool
opengl_renderer::Render( TSubRect *Groundsubcell ) {
Groundsubcell->RaAnimate(); // przeliczenia animacji torów w sektorze
TGroundNode *node;
// nieprzezroczyste obiekty terenu
// vbo render path
if( Groundsubcell->StartVBO() ) {
for( node = Groundsubcell->nRenderRect; node; node = node->nNext3 ) {
if( node->iVboPtr >= 0 ) {
Render( node );
}
}
Groundsubcell->EndVBO();
}
// nieprzezroczyste obiekty (oprócz pojazdów)
for( node = Groundsubcell->nRender; node; node = node->nNext3 )
Render( node );
// nieprzezroczyste z mieszanych modeli
for( node = Groundsubcell->nRenderMixed; node; node = node->nNext3 )
Render( node );
// nieprzezroczyste fragmenty pojazdów na torach
for( int j = 0; j < Groundsubcell->iTracks; ++j )
Groundsubcell->tTracks[ j ]->RenderDyn();
#ifdef EU07_SCENERY_EDITOR
// memcells
if( DebugModeFlag ) {
for( auto const memcell : m_memcells ) {
memcell->RenderDL();
}
}
#endif
return true;
}
bool
opengl_renderer::Render( TGroundNode *Node ) {
Node->SetLastUsage( Timer::GetSimulationTime() );
switch (Node->iType)
{ // obiekty renderowane niezależnie od odległości
case TP_SUBMODEL:
::glPushMatrix();
auto const originoffset = Node->pCenter - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
TSubModel::fSquareDist = 0;
Render( Node->smTerrain );
::glPopMatrix();
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: {
if( ( Node->iNumVerts <= 0 ) ) {
return false;
}
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// TODO: unify the render code after generic buffers are in place
// vbo render path
Node->pTrack->RaRenderVBO( Node->iVboPtr );
// post-render cleanup
::glPopMatrix();
return true;
}
case TP_MODEL: {
Node->Model->Render( Node->pCenter - Global::pCameraPosition );
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( ( 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.x ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::daylight.ambient.y ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::daylight.ambient.z ) ),
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
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
::glPopMatrix();
// post-render cleanup
return true;
}
else {
return false;
}
}
else {
// GL_TRIANGLE etc
if (Node->iVboPtr < 0) {
return false;
}
// 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
// vbo render path
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
::glPopMatrix();
// post-render cleanup
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 );
auto const originoffset = Dynamic->vPosition - Global::pCameraPosition;
double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
::glPushMatrix();
/*
if( Dynamic == Global::pUserDynamic ) {
//specjalne ustawienie, aby nie trzęsło
//tu trzeba by ustawić animacje na modelu zewnętrznym
@@ -335,7 +629,8 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
}
else
::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii
*/
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glMultMatrixd( Dynamic->mMatrix.getArray() );
if( Dynamic->fShade > 0.0f ) {
@@ -434,7 +729,8 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
if( Angle.z != 0.0 )
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
auto const result = Render( Model, Material, SquareMagnitude( Position - Global::GetCameraPosition() ) );
// auto const result = Render( Model, Material, SquareMagnitude( Position / Global::ZoomFactor ) ); // position is effectively camera offset
auto const result = Render( Model, Material, SquareMagnitude( Position ) ); // position is effectively camera offset
::glPopMatrix();
@@ -512,7 +808,7 @@ opengl_renderer::Render( TSubModel *Submodel, glm::mat4 m) {
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 ) {
glUseProgram(0);
@@ -590,7 +886,226 @@ opengl_renderer::Render( TSubModel *Submodel, glm::mat4 m) {
if( Submodel->Next )
if( Submodel->iAlpha & Submodel->iFlags & 0x1F000000 )
Render( Submodel->Next, m ); // dalsze rekurencyjnie
Render( Submodel->Next ); // dalsze rekurencyjnie
}
void
opengl_renderer::Render( TMemCell *Memcell ) {
::glPushAttrib( GL_ENABLE_BIT );
// ::glDisable( GL_LIGHTING );
::glDisable( GL_TEXTURE_2D );
// ::glEnable( GL_BLEND );
::glPushMatrix();
auto const position = Memcell->Position();
::glTranslated( position.x, position.y + 0.5, position.z );
::glColor3f( 0.36f, 0.75f, 0.35f );
::gluSphere( m_quadric, 0.35, 4, 2 );
::glPopMatrix();
::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 ];
// vbo render path
if( tmp->StartVBO() ) {
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
if( node->iVboPtr >= 0 ) {
Render_Alpha( node );
}
}
tmp->EndVBO();
}
}
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
{ // renderowanie przezroczystych modeli oraz pojazdów
Render_Alpha( Ground->pRendered[ i ] );
}
::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 ];
// vbo render path
if( tmp->StartVBO() ) {
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
Render_Alpha( node );
}
tmp->EndVBO();
}
}
return true;
}
bool
opengl_renderer::Render_Alpha( TSubRect *Groundsubcell ) {
TGroundNode *node;
for( node = Groundsubcell->nRenderMixed; node; node = node->nNext3 )
Render_Alpha( node ); // przezroczyste z mieszanych modeli
for( node = Groundsubcell->nRenderAlpha; node; node = node->nNext3 )
Render_Alpha( node ); // przezroczyste modele
for( int j = 0; j < Groundsubcell->iTracks; ++j )
Groundsubcell->tTracks[ j ]->RenderDynAlpha(); // przezroczyste fragmenty pojazdów na torach
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 ) {
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
Node->hvTraction->RenderVBO( distancesquared, Node->iVboPtr );
// post-render cleanup
::glPopMatrix();
return true;
}
else {
return false;
}
}
case TP_MODEL: {
Node->Model->RenderAlpha( Node->pCenter - Global::pCameraPosition );
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
// additional setup for display lists
if( ( Node->DisplayListID == 0 )
|| ( Node->iVersion != Global::iReCompile ) ) { // Ra: wymuszenie rekompilacji
Node->Compile(Node->m_rootposition);
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
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::daylight.ambient.x ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::daylight.ambient.y ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::daylight.ambient.z ) ),
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
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
// post-render cleanup
::glPopMatrix();
result = true;
}
}
else {
// GL_TRIANGLE etc
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::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
// vbo render path
if( Node->iVboPtr >= 0 ) {
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
result = true;
}
// post-render cleanup
::glPopMatrix();
}
#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
@@ -603,17 +1118,19 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
// setup
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
double squaredistance = SquareMagnitude( ( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor );
auto const originoffset = Dynamic->vPosition - Global::pCameraPosition;
double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
::glPushMatrix();
/*
if( Dynamic == Global::pUserDynamic ) { // specjalne ustawienie, aby nie trzęsło
::glLoadIdentity(); // zacząć od macierzy jedynkowej
Global::pCamera->SetCabMatrix( Dynamic->vPosition ); // specjalne ustawienie kamery
}
else
::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii
*/
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glMultMatrixd( Dynamic->mMatrix.getArray() );
if( Dynamic->fShade > 0.0f ) {
@@ -711,7 +1228,8 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
if( Angle.z != 0.0 )
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position - Global::GetCameraPosition() ) );
// auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position / Global::ZoomFactor ) ); // position is effectively camera offset
auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position ) ); // position is effectively camera offset
::glPopMatrix();
@@ -849,9 +1367,9 @@ opengl_renderer::Update ( double const Deltatime ) {
int targetsegments;
float targetfactor;
if( framerate > 65.0 ) { targetsegments = 400; targetfactor = 3.0f; }
else if( framerate > 40.0 ) { targetsegments = 225; targetfactor = 1.5f; }
else if( framerate > 15.0 ) { targetsegments = 90; targetfactor = Global::ScreenHeight / 768.0f; }
if( framerate > 90.0 ) { targetsegments = 400; targetfactor = 3.0f; }
else if( framerate > 60.0 ) { targetsegments = 225; targetfactor = 1.5f; }
else if( framerate > 30.0 ) { targetsegments = 90; targetfactor = Global::ScreenHeight / 768.0f; }
else { targetsegments = 9; targetfactor = Global::ScreenHeight / 768.0f * 0.75f; }
if( targetsegments > Global::iSegmentsRendered ) {

View File

@@ -14,6 +14,8 @@ http://mozilla.org/MPL/2.0/.
#include "lightarray.h"
#include "dumb3d.h"
#include "frustum.h"
#include "world.h"
#include "memcell.h"
#include "ground.h"
#include "shader.h"
#include "World.h"
@@ -42,7 +44,7 @@ public:
update_frustum() { m_frustum.calculate(); }
inline
void
update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); }
update_frustum(glm::mat4 const &Projection, glm::mat4 const &Modelview) { m_frustum.calculate(Projection, Modelview); }
bool
visible( bounding_area const &Area ) const;
bool
@@ -59,6 +61,9 @@ class opengl_renderer {
public:
// types
// destructor
~opengl_renderer() { gluDeleteQuadric( m_quadric ); }
// methods
bool
Init( GLFWwindow *Window );
@@ -69,6 +74,12 @@ public:
Render( world_environment *Environment );
bool
Render( TGround *Ground );
bool
Render( TGroundRect *Groundcell );
bool
Render( TSubRect *Groundsubcell );
bool
Render( TGroundNode *Node );
bool
Render( TDynamicObject *Dynamic );
bool
@@ -76,9 +87,17 @@ public:
bool
Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
void
Render( TSubModel *Submodel, glm::mat4 m );
void Render(TSubModel *Submodel);
Render( TSubModel *Submodel );
void Render(TSubModel *Submodel, glm::mat4 m);
void Render_Alpha(TSubModel *Submodel);
void
Render( TMemCell *Memcell );
bool
Render_Alpha( TGround *Ground );
bool
Render_Alpha( TSubRect *Groundsubcell );
bool
Render_Alpha( TGroundNode *Node );
bool
Render_Alpha( TDynamicObject *Dynamic );
bool
@@ -144,6 +163,8 @@ private:
texture_manager::size_type m_glaretextureid{ -1 };
texture_manager::size_type m_suntextureid{ -1 };
texture_manager::size_type m_moontextureid{ -1 };
GLUquadricObj *m_quadric; // helper object for drawing debug mode scene elements
};
extern opengl_renderer GfxRenderer;

27
sky.cpp
View File

@@ -31,39 +31,18 @@ void TSky::Render( float3 const &Tint )
{
if (mdCloud)
{ // jeśli jest model nieba
#ifdef EU07_USE_OLD_LIGHTING_MODEL
// TODO: re-implement this
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
#else
// setup
::glEnable( GL_LIGHTING );
GfxRenderer.Disable_Lights();
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &Tint.x );
#endif
#ifdef EU07_USE_OLD_RENDERCODE
if( Global::bUseVBO )
{ // renderowanie z VBO
mdCloud->RaRender( 100, 0 );
mdCloud->RaRenderAlpha(100, 0);
}
else
{ // renderowanie z Display List
mdCloud->Render(100, 0);
mdCloud->RenderAlpha(100, 0);
}
#else
// render
GfxRenderer.Render( mdCloud, nullptr, 100.0 );
GfxRenderer.Render_Alpha( mdCloud, nullptr, 100.0 );
#endif
#ifdef EU07_USE_OLD_LIGHTING_MODEL
glPopMatrix();
// TODO: re-implement this
glLightfv(GL_LIGHT0, GL_POSITION, Global::lightPos);
#else
// post-render cleanup
GLfloat noambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, noambient );
::glEnable( GL_LIGHT0 ); // other lights will be enabled during lights update
::glDisable( GL_LIGHTING );
#endif
}
};

View File

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

View File

@@ -258,8 +258,6 @@ void cSun::irradiance() {
static double degrad = 57.295779513; // converts from radians to degrees
static double raddeg = 0.0174532925; // converts from degrees to radians
auto const &localtime = simulation::Time.data(); // time for the calculation
m_body.dayang = ( simulation::Time.year_day() - 1 ) * 360.0 / 365.0;
double sd = sin( raddeg * m_body.dayang ); // sine of the day angle
double cd = cos( raddeg * m_body.dayang ); // cosine of the day angle or delination

View File

@@ -150,7 +150,7 @@ ui_layer::render_panels() {
glPushAttrib( GL_ENABLE_BIT );
glDisable( GL_TEXTURE_2D );
float const width = std::min( 4.0f / 3.0f, static_cast<float>(Global::iWindowWidth) / Global::iWindowHeight ) * Global::iWindowHeight;
float const width = std::min( 4.0f / 3.0f, static_cast<float>(Global::iWindowWidth) / std::max( 1, Global::iWindowHeight ) ) * Global::iWindowHeight;
float const height = Global::iWindowHeight / 768.0;
for( auto const &panel : m_panels ) {

View File

@@ -11,17 +11,6 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h"
#define SafeDelete(a) \
{ \
delete (a); \
a = nullptr; \
}
#define SafeDeleteArray(a) \
{ \
delete[](a); \
a = nullptr; \
}
#define sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))
#define DegToRad(a) ((M_PI / 180.0) * (a)) //(a) w nawiasie, bo może być dodawaniem
@@ -31,9 +20,22 @@ http://mozilla.org/MPL/2.0/.
#define asSceneryPath std::string("scenery\\")
#define szSceneryPath "scenery\\"
#define szTexturePath "textures\\"
#define szSoundPath "sounds\\"
#define MAKE_ID4(a,b,c,d) (((std::uint32_t)(d)<<24)|((std::uint32_t)(c)<<16)|((std::uint32_t)(b)<<8)|(std::uint32_t)(a))
template <typename _Type>
void SafeDelete( _Type &Pointer ) {
delete Pointer;
Pointer = nullptr;
}
template <typename _Type>
void SafeDeleteArray( _Type &Pointer ) {
delete[] Pointer;
Pointer = nullptr;
}
template <typename _Type>
_Type
clamp( _Type const Value, _Type const Min, _Type const Max ) {

5
version.h Normal file
View File

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

View File

@@ -17,26 +17,7 @@ http://mozilla.org/MPL/2.0/.
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "WavRead.h"
//-----------------------------------------------------------------------------
// Defines, constants, and global variables
//-----------------------------------------------------------------------------
#define SAFE_DELETE(p) \
{ \
if (p) \
{ \
delete (p); \
(p) = NULL; \
} \
}
#define SAFE_RELEASE(p) \
{ \
if (p) \
{ \
(p)->Release(); \
(p) = NULL; \
} \
}
#include "usefull.h"
//-----------------------------------------------------------------------------
// Name: ReadMMIO()
@@ -122,13 +103,13 @@ HRESULT ReadMMIO(HMMIO hmmioIn, MMCKINFO *pckInRIFF, WAVEFORMATEX **ppwfxInfo)
// so the data can be easily read with WaveReadFile. Returns 0 if
// successful, the error code if not.
//-----------------------------------------------------------------------------
HRESULT WaveOpenFile(CHAR *strFileName, HMMIO *phmmioIn, WAVEFORMATEX **ppwfxInfo,
HRESULT WaveOpenFile( std::string const &Filename, HMMIO *phmmioIn, WAVEFORMATEX **ppwfxInfo,
MMCKINFO *pckInRIFF)
{
HRESULT hr;
HMMIO hmmioIn = NULL;
if (NULL == (hmmioIn = mmioOpen(strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ)))
if (NULL == (hmmioIn = mmioOpen(const_cast<char*>(Filename.c_str()), NULL, MMIO_ALLOCBUF | MMIO_READ)))
return E_FAIL;
if (FAILED(hr = ReadMMIO(hmmioIn, pckInRIFF, ppwfxInfo)))
@@ -228,20 +209,20 @@ CWaveSoundRead::CWaveSoundRead()
CWaveSoundRead::~CWaveSoundRead()
{
Close();
SAFE_DELETE(m_pwfx);
SafeDelete(m_pwfx);
}
//-----------------------------------------------------------------------------
// Name: Open()
// Desc: Opens a wave file for reading
//-----------------------------------------------------------------------------
HRESULT CWaveSoundRead::Open(CHAR *strFilename)
HRESULT CWaveSoundRead::Open(std::string const &Filename)
{
SAFE_DELETE(m_pwfx);
SafeDelete(m_pwfx);
HRESULT hr;
if (FAILED(hr = WaveOpenFile(strFilename, &m_hmmioIn, &m_pwfx, &m_ckInRiff)))
if (FAILED(hr = WaveOpenFile(Filename, &m_hmmioIn, &m_pwfx, &m_ckInRiff)))
return hr;
if (FAILED(hr = Reset()))
@@ -276,6 +257,8 @@ HRESULT CWaveSoundRead::Read(UINT nSizeToRead, BYTE *pbData, UINT *pnSizeRead)
//-----------------------------------------------------------------------------
HRESULT CWaveSoundRead::Close()
{
mmioClose(m_hmmioIn, 0);
if( m_hmmioIn != NULL ) {
mmioClose( m_hmmioIn, 0 );
}
return S_OK;
}

View File

@@ -15,12 +15,12 @@ http://mozilla.org/MPL/2.0/.
//
// Copyright (c) 1999 Microsoft Corp. All rights reserved.
//-----------------------------------------------------------------------------
#ifndef WAVE_READ_H
#define WAVE_READ_H
#pragma once
#include <mmsystem.h>
#include <string>
HRESULT WaveOpenFile(CHAR *strFileName, HMMIO *phmmioIn, WAVEFORMATEX **ppwfxInfo,
HRESULT WaveOpenFile(std::string const &Filename, HMMIO *phmmioIn, WAVEFORMATEX **ppwfxInfo,
MMCKINFO *pckInRIFF);
HRESULT WaveStartDataRead(HMMIO *phmmioIn, MMCKINFO *pckIn, MMCKINFO *pckInRIFF);
HRESULT WaveReadFile(HMMIO hmmioIn, UINT cbRead, BYTE *pbDest, MMCKINFO *pckIn, UINT *cbActualRead);
@@ -33,7 +33,7 @@ class CWaveSoundRead
{
public:
WAVEFORMATEX *m_pwfx; // Pointer to WAVEFORMATEX structure
HMMIO m_hmmioIn; // MM I/O handle for the WAVE
HMMIO m_hmmioIn{ NULL }; // MM I/O handle for the WAVE
MMCKINFO m_ckIn; // Multimedia RIFF chunk
MMCKINFO m_ckInRiff; // Use in opening a WAVE file
@@ -41,10 +41,8 @@ class CWaveSoundRead
CWaveSoundRead();
~CWaveSoundRead();
HRESULT Open(CHAR *strFilename);
HRESULT Open(std::string const &Filename);
HRESULT Reset();
HRESULT Read(UINT nSizeToRead, BYTE *pbData, UINT *pnSizeRead);
HRESULT Close();
};
#endif WAVE_READ_H