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

Set dp branch as trunk

This commit is contained in:
ShaXbee
2015-04-03 13:34:06 +00:00
commit 45f4c0d98a
132 changed files with 94789 additions and 0 deletions

181
AdvSound.cpp Normal file
View File

@@ -0,0 +1,181 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Timer.h"
#include "AdvSound.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TAdvancedSound::TAdvancedSound()
{
// SoundStart=SoundCommencing=SoundShut= NULL;
State=ss_Off;
fTime=0;
fStartLength=0;
fShutLength=0;
}
__fastcall TAdvancedSound::~TAdvancedSound()
{//Ra: stopowanie siê sypie
//SoundStart.Stop();
//SoundCommencing.Stop();
//SoundShut.Stop();
}
void __fastcall TAdvancedSound::Free()
{
}
void __fastcall TAdvancedSound::Init(char *NameOn, char *Name, char *NameOff, double DistanceAttenuation, vector3 pPosition)
{
SoundStart.Init(NameOn,DistanceAttenuation,pPosition.x,pPosition.y,pPosition.z,true);
SoundCommencing.Init(Name,DistanceAttenuation,pPosition.x,pPosition.y,pPosition.z,true);
SoundShut.Init(NameOff,DistanceAttenuation,pPosition.x,pPosition.y,pPosition.z,true);
fStartLength=SoundStart.GetWaveTime();
fShutLength=SoundShut.GetWaveTime();
SoundStart.AM=1.0;
SoundStart.AA=0.0;
SoundStart.FM=1.0;
SoundStart.FA=0.0;
SoundCommencing.AM=1.0;
SoundCommencing.AA=0.0;
SoundCommencing.FM=1.0;
SoundCommencing.FA=0.0;
defAM=1.0;
defFM=1.0;
SoundShut.AM=1.0;
SoundShut.AA=0.0;
SoundShut.FM=1.0;
SoundShut.FA=0.0;
}
void __fastcall TAdvancedSound::Load(TQueryParserComp *Parser, vector3 pPosition)
{
AnsiString NameOn= Parser->GetNextSymbol().LowerCase();
AnsiString Name= Parser->GetNextSymbol().LowerCase();
AnsiString NameOff= Parser->GetNextSymbol().LowerCase();
double DistanceAttenuation= Parser->GetNextSymbol().ToDouble();
Init(NameOn.c_str(),Name.c_str(),NameOff.c_str(),DistanceAttenuation,pPosition);
}
void __fastcall TAdvancedSound::TurnOn(bool ListenerInside, vector3 NewPosition)
{
//hunter-311211: nie trzeba czekac na ponowne odtworzenie dzwieku, az sie wylaczy
if ((State==ss_Off || State==ss_ShuttingDown) && (SoundStart.AM>0))
{
SoundStart.ResetPosition();
SoundCommencing.ResetPosition();
SoundStart.Play(1,0,ListenerInside,NewPosition);
// SoundStart->SetVolume(-10000);
State= ss_Starting;
fTime= 0;
}
}
void __fastcall TAdvancedSound::TurnOff(bool ListenerInside, vector3 NewPosition)
{
if ((State==ss_Commencing || State==ss_Starting) && (SoundShut.AM>0))
{
SoundStart.Stop();
SoundCommencing.Stop();
SoundShut.ResetPosition();
SoundShut.Play(1,0,ListenerInside,NewPosition);
State= ss_ShuttingDown;
fTime= fShutLength;
// SoundShut->SetVolume(0);
}
}
void __fastcall TAdvancedSound::Update(bool ListenerInside, vector3 NewPosition)
{
if ((State==ss_Commencing) && (SoundCommencing.AM>0))
{
// SoundCommencing->SetFrequency();
SoundShut.Stop(); //hunter-311211
SoundCommencing.Play(1,DSBPLAY_LOOPING,ListenerInside,NewPosition);
}
else
if (State==ss_Starting)
{
fTime+= Timer::GetDeltaTime();
// SoundStart->SetVolume(-1000*(4-fTime)/4);
if (fTime>=fStartLength)
{
State= ss_Commencing;
SoundCommencing.ResetPosition();
SoundCommencing.Play(1,DSBPLAY_LOOPING,ListenerInside,NewPosition);
SoundStart.Stop();
}
else
SoundStart.Play(1,0,ListenerInside,NewPosition);
}
else
if (State==ss_ShuttingDown)
{
fTime-= Timer::GetDeltaTime();
// SoundShut->SetVolume(-1000*(4-fTime)/4);
if (fTime<=0)
{
State= ss_Off;
SoundShut.Stop();
}
else
SoundShut.Play(1,0,ListenerInside,NewPosition);
}
}
void __fastcall TAdvancedSound::UpdateAF(double A, double F, bool ListenerInside, vector3 NewPosition)
{ //update, ale z amplituda i czestotliwoscia
if ((State==ss_Commencing) && (SoundCommencing.AM>0))
{
SoundShut.Stop(); //hunter-311211
SoundCommencing.Play(A,DSBPLAY_LOOPING,ListenerInside,NewPosition);
}
else
if (State==ss_Starting)
{
fTime+= Timer::GetDeltaTime();
// SoundStart->SetVolume(-1000*(4-fTime)/4);
if (fTime>=fStartLength)
{
State= ss_Commencing;
SoundCommencing.ResetPosition();
SoundCommencing.Play(A,DSBPLAY_LOOPING,ListenerInside,NewPosition);
SoundStart.Stop();
}
else
SoundStart.Play(A,0,ListenerInside,NewPosition);
}
else
if (State==ss_ShuttingDown)
{
fTime-= Timer::GetDeltaTime();
// SoundShut->SetVolume(-1000*(4-fTime)/4);
if (fTime<=0)
{
State= ss_Off;
SoundShut.Stop();
}
else
SoundShut.Play(A,0,ListenerInside,NewPosition);
}
SoundCommencing.AdjFreq(F,Timer::GetDeltaTime());
}
void __fastcall TAdvancedSound::CopyIfEmpty(TAdvancedSound &s)
{//skopiowanie, gdyby by³ potrzebny, a nie zosta³ wczytany
if ((fStartLength>0.0)||(fShutLength>0.0)) return; //coœ jest
SoundStart=s.SoundStart;
SoundCommencing=s.SoundCommencing;
SoundShut=s.SoundShut;
State=s.State;
fStartLength=s.fStartLength;
fShutLength=s.fShutLength;
defAM=s.defAM;
defFM=s.defFM;
};

37
AdvSound.h Normal file
View File

@@ -0,0 +1,37 @@
//---------------------------------------------------------------------------
#ifndef AdvSoundH
#define AdvSoundH
#include "Sound.h"
#include "RealSound.h"
#include "QueryParserComp.hpp"
typedef enum {ss_Off, ss_Starting, ss_Commencing, ss_ShuttingDown} TSoundState;
class TAdvancedSound
{//klasa dŸwiêków maj¹cych pocz¹tek, dowolnie d³ugi œrodek oraz zakoñczenie (np. Rp1)
TRealSound SoundStart;
TRealSound SoundCommencing;
TRealSound SoundShut;
TSoundState State;
double fTime;
double fStartLength;
double fShutLength;
double defAM;
double defFM;
public:
__fastcall TAdvancedSound();
__fastcall ~TAdvancedSound();
void __fastcall Init(char *NameOn, char *Name, char *NameOff, double DistanceAttenuation, vector3 pPosition);
void __fastcall Load(TQueryParserComp *Parser, vector3 pPosition);
void __fastcall TurnOn(bool ListenerInside, vector3 NewPosition);
void __fastcall TurnOff(bool ListenerInside, vector3 NewPosition);
void __fastcall Free();
void __fastcall Update(bool ListenerInside, vector3 NewPosition);
void __fastcall UpdateAF(double A, double F, bool ListenerInside, vector3 NewPosition);
void __fastcall CopyIfEmpty(TAdvancedSound &s);
};
//---------------------------------------------------------------------------
#endif

73
AirCoupler.cpp Normal file
View File

@@ -0,0 +1,73 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "AirCoupler.h"
#include "Timer.h"
__fastcall TAirCoupler::TAirCoupler()
{
Clear();
}
__fastcall TAirCoupler::~TAirCoupler()
{
}
int __fastcall TAirCoupler::GetStatus()
{//zwraca 1, jeœli istnieje model prosty, 2 gdy skoœny
int x=0;
if (pModelOn) x=1;
if (pModelxOn) x=2;
return x;
}
void __fastcall TAirCoupler::Clear()
{//zerowanie wskaŸników
pModelOn=NULL;
pModelOff=NULL;
pModelxOn=NULL;
bOn=false;
bxOn=false;
}
void __fastcall TAirCoupler::Init(AnsiString asName, TModel3d *pModel)
{//wyszukanie submodeli
if (!pModel) return; //nie ma w czym szukaæ
pModelOn=pModel->GetFromName(AnsiString(asName+"_on").c_str()); //po³¹czony na wprost
pModelOff=pModel->GetFromName(AnsiString(asName+"_off").c_str()); //odwieszony
pModelxOn=pModel->GetFromName(AnsiString(asName+"_xon").c_str()); //po³¹czony na skos
}
void __fastcall TAirCoupler::Load(TQueryParserComp *Parser, TModel3d *pModel)
{
AnsiString str=Parser->GetNextSymbol().LowerCase();
if (pModel)
Init(str,pModel);
else
{
pModelOn=NULL;
pModelxOn=NULL;
pModelOff=NULL;
}
}
void __fastcall TAirCoupler::Update()
{
// if ((pModelOn!=NULL) && (pModelOn!=NULL))
{
if (pModelOn)
pModelOn->iVisible=bOn;
if (pModelOff)
pModelOff->iVisible=!(bOn||bxOn);
if (pModelxOn)
pModelxOn->iVisible=bxOn;
}
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

32
AirCoupler.h Normal file
View File

@@ -0,0 +1,32 @@
//---------------------------------------------------------------------------
#ifndef AirCouplerH
#define AirCouplerH
#include "Model3d.h"
#include "QueryParserComp.hpp"
class TAirCoupler
{
private:
// TButtonType eType;
TSubModel *pModelOn,*pModelOff,*pModelxOn;
bool bOn;
bool bxOn;
void __fastcall Update();
public:
__fastcall TAirCoupler();
__fastcall ~TAirCoupler();
void __fastcall Clear();
inline void TurnOn() { bOn=true; bxOn=false; Update(); };
inline void TurnOff() { bOn=false; bxOn=false; Update(); };
inline void TurnxOn() { bOn=false; bxOn=true; Update(); };
// inline bool Active() { if ((pModelOn)||(pModelOff)) return true; return false;};
int __fastcall GetStatus();
void __fastcall Init(AnsiString asName, TModel3d *pModel);
void __fastcall Load(TQueryParserComp *Parser, TModel3d *pModel);
// bool __fastcall Render();
};
//---------------------------------------------------------------------------
#endif

787
AnimModel.cpp Normal file
View File

@@ -0,0 +1,787 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "AnimModel.h"
#include "usefull.h"
#include "Timer.h"
#include "MdlMngr.h"
//McZapkie:
#include "Texture.h"
#include "Globals.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TAnimAdvanced::TAnimAdvanced()
{
};
__fastcall TAnimAdvanced::~TAnimAdvanced()
{
//delete[] pVocaloidMotionData; //plik został zmodyfikowany
};
int __fastcall TAnimAdvanced::SortByBone()
{//sortowanie pliku animacji w celu optymalniejszego wykonania
//rekordy zostają ułożone wg kolejnych ramek dla każdej kości
//ułożenie kości alfabetycznie nie jest niezbędne, ale upraszcza sortowanie bąbelkowe
TAnimVocaloidFrame buf; //bufor roboczy (przydało by się pascalowe Swap()
int i,j,k,swaps=0,last=iMovements-1,e;
for (i=0;i<iMovements;++i)
for (j=0;j<15;++j)
if (pMovementData[i].cBone[j]=='\0') //jeśli znacznik końca
for (++j;j<15;++j)
pMovementData[i].cBone[j]='\0'; //zerowanie bajtów za znacznikiem końca
for (i=0;i<last;++i) //do przedostatniego
{//dopóki nie posortowane
j=i; //z którym porównywać
k=i; //z którym zamienić (nie trzeba zamieniać, jeśli ==i)
while (++j<iMovements)
{e=strcmp(pMovementData[k].cBone,pMovementData[j].cBone); //numery trzeba porównywać inaczej
if (e>0)
k=j; //trzeba zamienić - ten pod j jest mniejszy
else if (!e)
if (pMovementData[k].iFrame>pMovementData[j].iFrame)
k=j; //numer klatki pod j jest mniejszy
}
if (k>i)
{//jeśli trzeba przestawić
//buf=pMovementData[i];
//pMovementData[i]=pMovementData[k];
//pMovementData[k]=buf;
memcpy(&buf,pMovementData+i,sizeof(TAnimVocaloidFrame));
memcpy(pMovementData+i,pMovementData+k,sizeof(TAnimVocaloidFrame));
memcpy(pMovementData+k,&buf,sizeof(TAnimVocaloidFrame));
++swaps;
}
}
return swaps;
};
__fastcall TAnimContainer::TAnimContainer()
{
pNext=NULL;
vRotateAngles=vector3(0.0f,0.0f,0.0f); //aktualne kąty obrotu
vDesiredAngles=vector3(0.0f,0.0f,0.0f); //docelowe kąty obrotu
fRotateSpeed=0.0;
vTranslation=vector3(0.0f,0.0f,0.0f); //aktualne przesunięcie
vTranslateTo=vector3(0.0f,0.0f,0.0f); //docelowe przesunięcie
fTranslateSpeed=0.0;
fAngleSpeed=0.0;
pSubModel=NULL;
iAnim=0; //położenie początkowe
pMovementData=NULL; //nie ma zaawansowanej animacji
mAnim=NULL; //nie ma macierzy obrotu dla submodelu
evDone=NULL; //powiadamianie o zakończeniu animacji
acAnimNext=NULL; //na razie jest poza listą
}
__fastcall TAnimContainer::~TAnimContainer()
{
SafeDelete(pNext);
delete mAnim; //AnimContainer jest właścicielem takich macierzy
}
bool __fastcall TAnimContainer::Init(TSubModel *pNewSubModel)
{
fRotateSpeed=0.0f;
pSubModel=pNewSubModel;
return (pSubModel!=NULL);
}
void __fastcall TAnimContainer::SetRotateAnim(vector3 vNewRotateAngles, double fNewRotateSpeed)
{
if (!this) return; //wywoływane z eventu, gdy brak modelu
vDesiredAngles=vNewRotateAngles;
fRotateSpeed=fNewRotateSpeed;
iAnim|=1;
/* //Ra 2014-07: jeśli model nie jest renderowany, to obliczyć czas animacji i dodać event wewnętrzny
//można by też ustawić czas początku animacji zamiast pobierać czas ramki i liczyć różnicę
*/
if (evDone)
{//dołączyć model do listy aniomowania, żeby animacje były przeliczane również bez wyświetlania
if (iAnim>=0)
{//jeśli nie jest jeszcze na liście animacyjnej
acAnimNext=TAnimModel::acAnimList; //pozostałe doklić sobie jako ogon
TAnimModel::acAnimList=this; //a wstawić się na początek
iAnim|=0x80000000; //dodany do listy
}
}
}
void __fastcall TAnimContainer::SetTranslateAnim(vector3 vNewTranslate, double fNewSpeed)
{
if (!this) return; //wywoływane z eventu, gdy brak modelu
vTranslateTo=vNewTranslate;
fTranslateSpeed=fNewSpeed;
iAnim|=2;
/* //Ra 2014-07: jeśli model nie jest renderowany, to obliczyć czas animacji i dodać event wewnętrzny
//można by też ustawić czas początku animacji zamiast pobierać czas ramki i liczyć różnicę
*/
if (evDone)
{//dołączyć model do listy aniomowania, żeby animacje były przeliczane również bez wyświetlania
if (iAnim>=0)
{//jeśli nie jest jeszcze na liście animacyjnej
acAnimNext=TAnimModel::acAnimList; //pozostałe doklić sobie jako ogon
TAnimModel::acAnimList=this; //a wstawić się na początek
iAnim|=0x80000000; //dodany do listy
}
}
}
void __fastcall TAnimContainer::AnimSetVMD(double fNewSpeed)
{
if (!this) return; //wywoływane z eventu, gdy brak modelu
//skala do ustalenia, "cal" japoński (sun) to nieco ponad 3cm
//X-w lewo, Y-w górę, Z-do tyłu
//minimalna wysokość to -7.66, a nadal musi być ponad podłogą
//if (pMovementData->iFrame>0) return; //tylko pierwsza ramka
vTranslateTo=vector3(0.1*pMovementData->f3Vector.x,0.1*pMovementData->f3Vector.z,0.1*pMovementData->f3Vector.y);
if (LengthSquared3(vTranslateTo)>0.0?true:LengthSquared3(vTranslation)>0.0)
{//jeśli ma być przesunięte albo jest przesunięcie
iAnim|=2; //wyłączy się samo
if (fNewSpeed>0.0)
fTranslateSpeed=fNewSpeed; //prędkość jest mnożnikiem, nie podlega skalowaniu
else //za późno na animacje, trzeba przestawić
vTranslation=vTranslateTo;
}
//if ((qCurrent.w<1.0)||(pMovementData->qAngle.w<1.0))
{//jeśli jest jakiś obrót
if (!mAnim)
{mAnim=new float4x4(); //będzie potrzebna macierz animacji
mAnim->Identity(); //jedynkowanie na początek
}
iAnim|=4; //animacja kwaternionowa
qStart=qCurrent; //potrzebna początkowa do interpolacji
//---+ - też niby dobrze, ale nie tak trąca włosy na początku (macha w dół)
//-+-+ - dłoń ma w górze zamiast na pasie w pozycji początkowej
//+--+ - głowa do tyłu (broda w górę) w pozycji początkowej
//--++ - pozycja początkowa dobra, trąca u góry, ale z rękami jakoś nie tak, kółko w przeciwną stronę
//++++ - kładzie się brzuchem do góry
//-+++ - ręce w górze na początku, zamiast w dół, łokieć jakby w przeciwną stronę
//+-++ - nie podnosi ręki do głowy
//++-+ - dłoń ma w górze zamiast na pasie
qDesired=Normalize(float4(-pMovementData->qAngle.x,-pMovementData->qAngle.z,-pMovementData->qAngle.y,pMovementData->qAngle.w)); //tu trzeba będzie osie zamienić
if (fNewSpeed>0.0)
{fAngleSpeed=fNewSpeed; //wtedy animować za pomocą interpolacji
fAngleCurrent=0.0; //początek interpolacji
}
else
{//za późno na animację, można tylko przestawić w docelowe miejsce
fAngleSpeed=0.0;
fAngleCurrent=1.0; //interpolacja zakończona
qCurrent=qDesired;
}
}
//if (!strcmp(pSubModel->pName,"?Z?“?^?[")) //jak główna kość
//if (!strcmp(pSubModel->pName,"Ť¶‚‚Ü?ćhj")) //IK lewej stopy
// WriteLog(AnsiString(pMovementData->iFrame)+": "+AnsiString(pMovementData->f3Vector.x)+" "+AnsiString(pMovementData->f3Vector.y)+" "+AnsiString(pMovementData->f3Vector.z));
}
void __fastcall TAnimContainer::UpdateModel()
{//przeliczanie animacji wykonać tylko raz na model
if (pSubModel) //pozbyć się tego - sprawdzać wcześniej
{
if (fTranslateSpeed!=0.0)
{
vector3 dif=vTranslateTo-vTranslation; //wektor w kierunku docelowym
double l=LengthSquared3(dif); //długość wektora potrzebnego przemieszczenia
if (l>=0.0001)
{//jeśli do przemieszczenia jest ponad 1cm
vector3 s=SafeNormalize(dif); //jednostkowy wektor kierunku
s=s*(fTranslateSpeed*Timer::GetDeltaTime()); //przemieszczenie w podanym czasie z daną prędkością
if (LengthSquared3(s)<l) //żeby nie jechało na drugą stronę
vTranslation+=s;
else
vTranslation=vTranslateTo; //koniec animacji, "koniec animowania" uruchomi się w następnej klatce
}
else
{//koniec animowania
vTranslation=vTranslateTo;
fTranslateSpeed=0.0; //wyłączenie przeliczania wektora
if (LengthSquared3(vTranslation)<=0.0001) //jeśli jest w punkcie początkowym
iAnim&=~2; //wyłączyć zmianę pozycji submodelu
if (evDone) Global::AddToQuery(evDone,NULL); //wykonanie eventu informującego o zakończeniu
}
}
if (fRotateSpeed!=0)
{
/*
double dif= fDesiredAngle-fAngle;
double s= fRotateSpeed*sign(dif)*Timer::GetDeltaTime();
if ((abs(s)-abs(dif))>0)
fAngle= fDesiredAngle;
else
fAngle+= s;
while (fAngle>360) fAngle-= 360;
while (fAngle<-360) fAngle+= 360;
pSubModel->SetRotate(vRotateAxis,fAngle);
*/
bool anim=false;
vector3 dif=vDesiredAngles-vRotateAngles;
double s;
s=fRotateSpeed*sign(dif.x)*Timer::GetDeltaTime();
if (fabs(s)>=fabs(dif.x))
vRotateAngles.x=vDesiredAngles.x;
else
{vRotateAngles.x+=s; anim=true;}
s=fRotateSpeed*sign(dif.y)*Timer::GetDeltaTime();
if (fabs(s)>=fabs(dif.y))
vRotateAngles.y=vDesiredAngles.y;
else
{vRotateAngles.y+=s; anim=true;}
s=fRotateSpeed*sign(dif.z)*Timer::GetDeltaTime();
if (fabs(s)>=fabs(dif.z))
vRotateAngles.z=vDesiredAngles.z;
else
{vRotateAngles.z+=s; anim=true;}
while (vRotateAngles.x>= 360) vRotateAngles.x-=360;
while (vRotateAngles.x<=-360) vRotateAngles.x+=360;
while (vRotateAngles.y>= 360) vRotateAngles.y-=360;
while (vRotateAngles.y<=-360) vRotateAngles.y+=360;
while (vRotateAngles.z>= 360) vRotateAngles.z-=360;
while (vRotateAngles.z<=-360) vRotateAngles.z+=360;
if (vRotateAngles.x==0.0)
if (vRotateAngles.y==0.0)
if (vRotateAngles.z==0.0)
iAnim&=~1; //kąty są zerowe
if (!anim)
{//nie potrzeba przeliczać już
fRotateSpeed=0.0;
if (evDone) Global::AddToQuery(evDone,NULL); //wykonanie eventu informującego o zakończeniu
}
}
if (fAngleSpeed!=0.0)
{//obrót kwaternionu (interpolacja)
}
}
};
void __fastcall TAnimContainer::PrepareModel()
{//tutaj zostawić tylko ustawienie submodelu, przeliczanie ma być w UpdateModel()
if (pSubModel) //pozbyć się tego - sprawdzać wcześniej
{
//nanoszenie animacji na wzorzec
if (iAnim&1) //zmieniona pozycja względem początkowej
pSubModel->SetRotateXYZ(vRotateAngles); //ustawia typ animacji
if (iAnim&2) //zmieniona pozycja względem początkowej
pSubModel->SetTranslate(vTranslation);
if (iAnim&4) //zmieniona pozycja względem początkowej
{
if (fAngleSpeed>0.0f)
{fAngleCurrent+=fAngleSpeed*Timer::GetDeltaTime(); //aktualny parametr interpolacji
if (fAngleCurrent>=1.0f)
{//interpolacja zakończona, ustawienie na pozycję końcową
qCurrent=qDesired;
fAngleSpeed=0.0; //wyłączenie przeliczania wektora
if (evDone) Global::AddToQuery(evDone,NULL); //wykonanie eventu informującego o zakończeniu
}
else
{//obliczanie pozycji pośredniej
//normalizacja jest wymagana do interpolacji w następnej animacji
qCurrent=Normalize(Slerp(qStart,qDesired,fAngleCurrent)); //interpolacja sferyczna kąta
//qCurrent=Slerp(qStart,qDesired,fAngleCurrent); //interpolacja sferyczna kąta
if (qCurrent.w==1.0) //rozpoznać brak obrotu i wyłączyć w iAnim w takim przypadku
iAnim&=~4; //kąty są zerowe
}
}
mAnim->Quaternion(&qCurrent); //wypełnienie macierzy (wymaga normalizacji?)
pSubModel->mAnimMatrix=mAnim; //użyczenie do submodelu (na czas renderowania!)
}
}
//if (!strcmp(pSubModel->pName,"?Z?“?^?[")) //jak główna kość
// WriteLog(AnsiString(pMovementData->iFrame)+": "+AnsiString(iAnim)+" "+AnsiString(vTranslation.x)+" "+AnsiString(vTranslation.y)+" "+AnsiString(vTranslation.z));
}
void __fastcall TAnimContainer::UpdateModelIK()
{//odwrotna kinematyka wyliczana dopiero po ustawieniu macierzy w submodelach
if (pSubModel) //pozbyć się tego - sprawdzać wcześniej
{
if (pSubModel->b_Anim&at_IK)
{//odwrotna kinematyka
float3 d,k;
TSubModel *ch=pSubModel->ChildGet();
switch (pSubModel->b_Anim)
{
case at_IK11: //stopa: ustawić w kierunku czubka (pierwszy potomny)
d=ch->Translation1Get(); //wektor względem aktualnego układu (nie uwzględnia obrotu)
k=float3(RadToDeg(atan2(d.z,hypot(d.x,d.y))),0.0,-RadToDeg(atan2(d.y,d.x))); //proste skierowanie na punkt
pSubModel->SetRotateIK1(k);
//if (!strcmp(pSubModel->pName,"?Z?“?^?[")) //jak główna kość
// WriteLog("--> "+AnsiString(k.x)+" "+AnsiString(k.y)+" "+AnsiString(k.z));
//Ra: to już jest dobrze, może być inna ćwiartka i znak
break;
case at_IK22: //udo: ustawić w kierunku pierwszej potomnej pierwszej potomnej (kostki)
//pozycję kostki należy określić względem kości centralnej (+biodro może być pochylone)
//potem wyliczyć ewentualne odchylenie w tej i następnej
//w sumie to proste, jak wyznaczenie kątów w trójkącie o znanej długości boków...
d=ch->Translation2Get(); //wektor względem aktualnego układu (nie uwzględnia obrotu)
//if ()
{//kość IK jest dalej niż pozycja spoczynkowa
k=float3(RadToDeg(atan2(d.z,hypot(d.x,d.y))),0.0,-RadToDeg(atan2(d.y,d.x))); //proste skierowanie na punkt
pSubModel->SetRotateIK1(k);
}
break;
}
}
}
}
bool __fastcall TAnimContainer::InMovement()
{//czy trwa animacja - informacja dla obrotnicy
return (fRotateSpeed!=0.0)||(fTranslateSpeed!=0.0);
}
void __fastcall TAnimContainer::EventAssign(TEvent *ev)
{//przypisanie eventu wykonywanego po zakończeniu animacji
evDone=ev;
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
__fastcall TAnimModel::TAnimModel()
{
pRoot=NULL;
pModel=NULL;
iNumLights=0;
fBlinkTimer=0;
ReplacableSkinId[0]=0;
ReplacableSkinId[1]=0;
ReplacableSkinId[2]=0;
ReplacableSkinId[3]=0;
ReplacableSkinId[4]=0;
for (int i=0;i<iMaxNumLights;i++)
{
LightsOn[i]=LightsOff[i]=NULL; //normalnie nie ma
lsLights[i]=ls_Off; //a jeśli są, to wyłączone
}
vAngle.x=vAngle.y=vAngle.z=0.0; //zerowanie obrotów egzemplarza
pAdvanced=NULL; //nie ma zaawansowanej animacji
fDark=0.25; //standardowy próg zaplania
fOnTime=0.66;
fOffTime=fOnTime+0.66;
}
__fastcall TAnimModel::~TAnimModel()
{
delete pAdvanced; //nie ma zaawansowanej animacji
SafeDelete(pRoot);
}
bool __fastcall TAnimModel::Init(TModel3d *pNewModel)
{
fBlinkTimer=double(random(1000*fOffTime))/(1000*fOffTime);;
pModel=pNewModel;
return (pModel!=NULL);
}
bool __fastcall TAnimModel::Init(AnsiString asName, AnsiString asReplacableTexture)
{
if (asReplacableTexture.SubString(1,1)=="*") //od gwiazdki zaczynają się teksty na wyświetlaczach
asText=asReplacableTexture.SubString(2,asReplacableTexture.Length()-1); //zapamiętanie tekstu
else if (asReplacableTexture!="none")
ReplacableSkinId[1]=TTexturesManager::GetTextureID(NULL,NULL,asReplacableTexture.c_str());
if (TTexturesManager::GetAlpha(ReplacableSkinId[1]))
iTexAlpha=0x31310031; //tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych
else
iTexAlpha=0x30300030; //tekstura nieprzezroczysta - nie renderować w cyklu przezroczystych
return (Init(TModelsManager::GetModel(asName.c_str())));
}
bool __fastcall TAnimModel::Load(cParser *parser, bool ter)
{//rozpoznanie wpisu modelu i ustawienie świateł
AnsiString str;
std::string token;
parser->getTokens(); //nazwa modelu
*parser >> token;
str=AnsiString(token.c_str());
parser->getTokens(1,false); //tekstura (zmienia na małe)
*parser >> token;
if (!Init(str,AnsiString(token.c_str())))
{if (str!="notload")
{//gdy brak modelu
if (ter) //jeśli teren
{if (str.SubString(str.Length()-3,4)==".t3d")
str[str.Length()-2]='e';
Global::asTerrainModel=str;
WriteLog(AnsiString("Terrain model \""+str+"\" will be created."));
}
else
ErrorLog(AnsiString("Missed file: "+str));
}
}
else
{//wiązanie świateł, o ile model wczytany
LightsOn[0]=pModel->GetFromName("Light_On00");
LightsOn[1]=pModel->GetFromName("Light_On01");
LightsOn[2]=pModel->GetFromName("Light_On02");
LightsOn[3]=pModel->GetFromName("Light_On03");
LightsOn[4]=pModel->GetFromName("Light_On04");
LightsOn[5]=pModel->GetFromName("Light_On05");
LightsOn[6]=pModel->GetFromName("Light_On06");
LightsOn[7]=pModel->GetFromName("Light_On07");
LightsOff[0]=pModel->GetFromName("Light_Off00");
LightsOff[1]=pModel->GetFromName("Light_Off01");
LightsOff[2]=pModel->GetFromName("Light_Off02");
LightsOff[3]=pModel->GetFromName("Light_Off03");
LightsOff[4]=pModel->GetFromName("Light_Off04");
LightsOff[5]=pModel->GetFromName("Light_Off05");
LightsOff[6]=pModel->GetFromName("Light_Off06");
LightsOff[7]=pModel->GetFromName("Light_Off07");
}
for (int i=0;i<iMaxNumLights;++i)
if (LightsOn[i]||LightsOff[i]) //Ra: zlikwidowałem wymóg istnienia obu
iNumLights=i+1;
int i=0;
int ti;
parser->getTokens();
*parser >> token;
if (token.compare( "lights" ) == 0)
{
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
do
{
ti=str.ToDouble(); //stan światła jest liczbą z ułamkiem
LightSet(i,ti);
i++;
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
} while (str!="endmodel");
}
return true;
}
TAnimContainer* __fastcall TAnimModel::AddContainer(char *pName)
{//dodanie sterowania submodelem dla egzemplarza
if (!pModel) return NULL;
TSubModel *tsb=pModel->GetFromName(pName);
if (tsb)
{
TAnimContainer *tmp=new TAnimContainer();
tmp->Init(tsb);
tmp->pNext=pRoot;
pRoot=tmp;
return tmp;
}
return NULL;
}
TAnimContainer* __fastcall TAnimModel::GetContainer(char *pName)
{//szukanie/dodanie sterowania submodelem dla egzemplarza
if (!pName) return pRoot; //pobranie pierwszego (dla obrotnicy)
TAnimContainer *pCurrent;
for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext)
//if (pCurrent->GetName()==pName)
if (stricmp(pCurrent->NameGet(),pName)==0)
return pCurrent;
return AddContainer(pName);
}
void __fastcall TAnimModel::RaAnimate()
{//przeliczenie animacji - jednorazowo na klatkę
//Ra 2F1I: to by można pomijać dla modeli bez animacji, których jest większość
TAnimContainer *pCurrent;
for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext)
if (!pCurrent->evDone) //jeśli jest bez eventu
pCurrent->UpdateModel(); //przeliczenie animacji każdego submodelu
//if () //tylko dla modeli z IK !!!!
for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext) //albo osobny łańcuch
pCurrent->UpdateModelIK(); //przeliczenie odwrotnej kinematyki
};
void __fastcall TAnimModel::RaPrepare()
{//ustawia światła i animacje we wzorcu modelu przed renderowaniem egzemplarza
fBlinkTimer-=Timer::GetDeltaTime();
if (fBlinkTimer<=0) fBlinkTimer=fOffTime;
bool state; //stan światła
for (int i=0;i<iNumLights;i++)
{switch (lsLights[i])
{case ls_Blink: //migotanie
state=fBlinkTimer<fOnTime; break;
case ls_Dark: //zapalone, gdy ciemno
state=Global::fLuminance<=fDark; break;
default: //zapalony albo zgaszony
state=(lsLights[i]==ls_On);
}
if (LightsOn[i]) LightsOn[i]->iVisible=state;
if (LightsOff[i]) LightsOff[i]->iVisible=!state;
}
TSubModel::iInstance=(int)this; //żeby nie robić cudzych animacji
TSubModel::pasText=&asText; //przekazanie tekstu do wyświetlacza (!!!! do przemyślenia)
if (pAdvanced) //jeśli jest zaawansowana animacja
Advanced(); //wykonać co tam trzeba
TAnimContainer *pCurrent;
for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext)
pCurrent->PrepareModel(); //ustawienie animacji egzemplarza dla każdego submodelu
//if () //tylko dla modeli z IK !!!!
// for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext) //albo osobny łańcuch
// pCurrent->UpdateModelIK(); //przeliczenie odwrotnej kinematyki
}
void __fastcall 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 __fastcall TAnimModel::RenderAlphaVBO(vector3 pPosition,double fAngle)
{
RaPrepare();
if (pModel) //renderowanie rekurencyjne submodeli
pModel->RaRenderAlpha(pPosition,fAngle,ReplacableSkinId,iTexAlpha);
};
void __fastcall TAnimModel::RenderDL(vector3 pPosition,double fAngle)
{
RaAnimate(); //jednorazowe przeliczenie animacji
RaPrepare();
if (pModel) //renderowanie rekurencyjne submodeli
pModel->Render(pPosition,fAngle,ReplacableSkinId,iTexAlpha);
}
void __fastcall TAnimModel::RenderAlphaDL(vector3 pPosition,double fAngle)
{
RaPrepare();
if (pModel)
pModel->RenderAlpha(pPosition,fAngle,ReplacableSkinId,iTexAlpha);
};
int __fastcall 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;
};
//-----------------------------------------------------------------------------
//2011-03-16 cztery nowe funkcje renderowania z możliwością pochylania obiektów
//-----------------------------------------------------------------------------
void __fastcall TAnimModel::RenderDL(vector3* vPosition)
{
RaAnimate(); //jednorazowe przeliczenie animacji
RaPrepare();
if (pModel) //renderowanie rekurencyjne submodeli
pModel->Render(vPosition,&vAngle,ReplacableSkinId,iTexAlpha);
};
void __fastcall TAnimModel::RenderAlphaDL(vector3* vPosition)
{
RaPrepare();
if (pModel) //renderowanie rekurencyjne submodeli
pModel->RenderAlpha(vPosition,&vAngle,ReplacableSkinId,iTexAlpha);
};
void __fastcall TAnimModel::RenderVBO(vector3* vPosition)
{
RaAnimate(); //jednorazowe przeliczenie animacji
RaPrepare();
if (pModel) //renderowanie rekurencyjne submodeli
pModel->RaRender(vPosition,&vAngle,ReplacableSkinId,iTexAlpha);
};
void __fastcall TAnimModel::RenderAlphaVBO(vector3* vPosition)
{
RaPrepare();
if (pModel) //renderowanie rekurencyjne submodeli
pModel->RaRenderAlpha(vPosition,&vAngle,ReplacableSkinId,iTexAlpha);
};
//---------------------------------------------------------------------------
bool __fastcall TAnimModel::TerrainLoaded()
{//zliczanie kwadratów kilometrowych (główna linia po Next) do tworznia tablicy
return (this?pModel!=NULL:false);
};
int __fastcall TAnimModel::TerrainCount()
{//zliczanie kwadratów kilometrowych (główna linia po Next) do tworznia tablicy
return pModel?pModel->TerrainCount():0;
};
TSubModel* __fastcall TAnimModel::TerrainSquare(int n)
{//pobieranie wskaźników do pierwszego submodelu
return pModel?pModel->TerrainSquare(n):0;
};
void __fastcall TAnimModel::TerrainRenderVBO(int n)
{//renderowanie terenu z VBO
if (pModel) pModel->TerrainRenderVBO(n);
};
//---------------------------------------------------------------------------
void __fastcall TAnimModel::Advanced()
{//wykonanie zaawansowanych animacji na submodelach
pAdvanced->fCurrent+=pAdvanced->fFrequency*Timer::GetDeltaTime(); //aktualna ramka zmiennoprzecinkowo
int frame=floor(pAdvanced->fCurrent); //numer klatki jako int
TAnimContainer *pCurrent;
if (pAdvanced->fCurrent>=pAdvanced->fLast)
{//animacja została zakończona
delete pAdvanced;
pAdvanced=NULL; //dalej już nic
for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext)
if (pCurrent->pMovementData) //jeśli obsługiwany tabelką animacji
pCurrent->pMovementData=NULL; //usuwanie wskaźników
}
else
{//coś trzeba poanimować - wszystkie animowane submodele są w tym łańcuchu
for (pCurrent=pRoot;pCurrent!=NULL;pCurrent=pCurrent->pNext)
if (pCurrent->pMovementData) //jeśli obsługiwany tabelką animacji
if (frame>=pCurrent->pMovementData->iFrame) //koniec czekania
if (!strcmp(pCurrent->pMovementData->cBone,(pCurrent->pMovementData+1)->cBone))
{//jak kolejna ramka dotyczy tego samego submodelu, ustawić animację do kolejnej ramki
++pCurrent->pMovementData; //kolejna klatka
pCurrent->AnimSetVMD(pAdvanced->fFrequency/(double(pCurrent->pMovementData->iFrame)-pAdvanced->fCurrent));
}
else
pCurrent->pMovementData=NULL; //inna nazwa, animowanie zakończone w aktualnym położeniu
}
};
void __fastcall TAnimModel::AnimationVND(void* pData, double a, double b, double c, double d)
{//rozpoczęcie wykonywania animacji z podanego pliku
//tabela w pliku musi być posortowana wg klatek dla kolejnych kości!
//skrócone nagranie ma 3:42 = 222 sekundy, animacja kończy się na klatce 6518
//daje to 29.36 (~=30) klatek na sekundę
//w opisach jest podawane 24 albo 36 jako standard => powiedzmy, parametr (d) to FPS animacji
delete pAdvanced; //usunięcie ewentualnego poprzedniego
pAdvanced=NULL; //gdyby się nie udało rozpoznać pliku
if (AnsiString((char*)pData)=="Vocaloid Motion Data 0002")
{
pAdvanced=new TAnimAdvanced();
pAdvanced->pVocaloidMotionData=(char*)pData; //podczepienie pliku danych
pAdvanced->iMovements=*((int*)(((char*)pData)+50)); //numer ostatniej klatki
pAdvanced->pMovementData=(TAnimVocaloidFrame*)(((char*)pData)+54); //rekordy animacji
//WriteLog(sizeof(TAnimVocaloidFrame));
pAdvanced->fFrequency=d;
pAdvanced->fCurrent=0.0; //aktualna ramka
pAdvanced->fLast=0.0; //ostatnia ramka
/*
if (0) //jeśli włączone sortowanie plików VMD (trochę się przeciąga)
if (pAdvanced->SortByBone()) //próba posortowania
{//zapisać posortowany plik, jeśli dokonano zmian
TFileStream *fs=new TFileStream("models\\1.vmd",fmCreate);
fs->Write(pData,2198342); //2948728);
delete fs;
}
*/
int i,j,k,idx;
AnsiString name;
TAnimContainer *pSub;
for (i=0;i<pAdvanced->iMovements;++i)
{if (strcmp(pAdvanced->pMovementData[i].cBone,name.c_str()))
{//jeśli pozycja w tabelce nie była wyszukiwana w submodelach
pSub=GetContainer(pAdvanced->pMovementData[i].cBone); //szukanie
if (pSub) //znaleziony
{pSub->pMovementData=pAdvanced->pMovementData+i; //gotów do animowania
pSub->AnimSetVMD(0.0); //usuawienie pozycji początkowej (powinna być zerowa, inaczej będzie skok)
}
name=AnsiString(pAdvanced->pMovementData[i].cBone); //nowa nazwa do pomijania
}
if (pAdvanced->fLast<pAdvanced->pMovementData[i].iFrame)
pAdvanced->fLast=pAdvanced->pMovementData[i].iFrame;
}
/*
for (i=0;i<pAdvanced->iMovements;++i)
if (AnsiString(pAdvanced->pMovementData[i+1].cBone)!=AnsiString(pAdvanced->pMovementData[i].cBone))
{//generowane dla ostatniej klatki danej kości
name="";
for (j=0;j<15;j++)
name+=IntToHex((unsigned char)pAdvanced->pMovementData[i].cBone[j],2);
WriteLog(name+","
+AnsiString(pAdvanced->pMovementData[i].cBone)+","
+AnsiString(idx)+"," //indeks
+AnsiString(i+1-idx)+"," //ile pozycji animacji
+AnsiString(k)+"," //pierwsza klatka
+AnsiString(pAdvanced->pMovementData[i].iFrame)+"," //ostatnia klatka
+AnsiString(pAdvanced->pMovementData[i].f3Vector.x)+","
+AnsiString(pAdvanced->pMovementData[i].f3Vector.y)+","
+AnsiString(pAdvanced->pMovementData[i].f3Vector.z)+","
+AnsiString(pAdvanced->pMovementData[i].fAngle[0])+","
+AnsiString(pAdvanced->pMovementData[i].fAngle[1])+","
+AnsiString(pAdvanced->pMovementData[i].fAngle[2])+","
+AnsiString(pAdvanced->pMovementData[i].fAngle[3])
);
idx=i+1;
k=pAdvanced->pMovementData[i+1].iFrame; //pierwsza klatka następnego
}
else
if (pAdvanced->pMovementData[i].iFrame>0)
if ((k>pAdvanced->pMovementData[i].iFrame)||(k==0))
k=pAdvanced->pMovementData[i].iFrame; //pierwsza niezerowa ramka
*/
/*
for (i=0;i<pAdvanced->iMovements;++i)
if (AnsiString(pAdvanced->pMovementData[i].cBone)=="\x89\x45\x90\x65\x8E\x77\x82\x4F")
{name="";
for (j=0;j<15;j++)
name+=IntToHex((unsigned char)pAdvanced->pMovementData[i].cBone[j],2);
WriteLog(name+","
+AnsiString(i)+"," //pozycja w tabeli
+AnsiString(pAdvanced->pMovementData[i].iFrame)+"," //pierwsza klatka
);
}
*/
}
};
//---------------------------------------------------------------------------
void __fastcall TAnimModel::LightSet(int n,float v)
{//ustawienie światła (n) na wartość (v)
if (n>=iMaxNumLights) return; //przekroczony zakres
lsLights[n]=TLightState(int(v));
switch (lsLights[n])
{//interpretacja ułamka zależnie od typu
case 0: //ustalenie czasu migotania, t<1s (f>1Hz), np. 0.1 => t=0.1 (f=10Hz)
break;
case 1: //ustalenie wypełnienia ułamkiem, np. 1.25 => zapalony przez 1/4 okresu
break;
case 2: //ustalenie częstotliwości migotania, f<1Hz (t>1s), np. 2.2 => f=0.2Hz (t=5s)
break;
case 3: //zapalenie świateł zależne od oświetlenia scenerii
if (v>3.0)
fDark=v-3.0; //ustawienie indywidualnego progu zapalania
else
fDark=0.25; //standardowy próg zaplania
break;
}
};
//---------------------------------------------------------------------------
void __fastcall 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
// }
p->UpdateModel();
p=p->acAnimNext; //na razie bez usuwania z listy, bo głównie obrotnica na nią wchodzi
}
};
//---------------------------------------------------------------------------

148
AnimModel.h Normal file
View File

@@ -0,0 +1,148 @@
//---------------------------------------------------------------------------
#ifndef AnimModelH
#define AnimModelH
#include "Model3d.h"
const int iMaxNumLights=8;
//typy stanu œwiate³
typedef enum {
ls_Off=0, //zgaszone
ls_On=1, //zapalone
ls_Blink=2, //migaj¹ce
ls_Dark=3 //Ra: zapalajce siê automatycznie, gdy zrobi siê ciemno
} TLightState;
class TAnimVocaloidFrame
{//ramka animacji typu Vocaloid Motion Data z programu MikuMikuDance
public:
char cBone[15]; //nazwa koœci, mo¿e byæ po japoñsku
int iFrame; //numer ramki
float3 f3Vector; //przemieszczenie
float4 qAngle; //kwaternion obrotu
char cBezier[64]; //krzywe Béziera do interpolacji dla x,y,z i obrotu
};
class TEvent;
class TAnimContainer
{//opakowanie submodelu, okreœlaj¹ce animacjê egzemplarza - obs³ugiwane jako lista
friend class TAnimModel;
private:
vector3 vRotateAngles; //dla obrotów Eulera
vector3 vDesiredAngles;
double fRotateSpeed;
vector3 vTranslation;
vector3 vTranslateTo;
double fTranslateSpeed; //mo¿e tu daæ wektor?
float4 qCurrent; //aktualny interpolowany
float4 qStart; //pozycja pocz¹tkowa (0 dla interpolacji)
float4 qDesired; //pozycja koñcowa (1 dla interpolacji)
float fAngleCurrent; //parametr interpolacyjny: 0=start, 1=docelowy
float fAngleSpeed; //zmiana parametru interpolacji w sekundach
TSubModel *pSubModel;
float4x4 *mAnim; //macierz do animacji kwaternionowych
//dla kinematyki odwróconej u¿ywane s¹ kwaterniony
float fLength; //d³ugoœæ koœci dla IK
int iAnim; //animacja: +1-obrót Eulera, +2-przesuw, +4-obrót kwaternionem, +8-IK
//+0x80000000: animacja z eventem, wykonywana poza wyœwietlaniem
//+0x100: pierwszy stopieñ IK - obróciæ w stronê pierwszego potomnego (dziecka)
//+0x200: drugi stopieñ IK - dostosowaæ do pozycji potomnego potomnego (wnuka)
union
{//mog¹ byæ animacje klatkowe ró¿nego typu, wskaŸniki u¿ywa AnimModel
TAnimVocaloidFrame *pMovementData; //wskaŸnik do klatki
};
TEvent *evDone; //ewent wykonywany po zakoñczeniu animacji, np. zapór, obrotnicy
public:
TAnimContainer *pNext;
TAnimContainer *acAnimNext; //lista animacji z eventem, które musz¹ byæ przeliczane równie¿ bez wyœwietlania
__fastcall TAnimContainer();
__fastcall ~TAnimContainer();
bool __fastcall Init(TSubModel *pNewSubModel);
//std::string inline __fastcall GetName() { return std::string(pSubModel?pSubModel->asName.c_str():""); };
//std::string inline __fastcall GetName() { return std::string(pSubModel?pSubModel->pName:""); };
char* __fastcall NameGet() {return (pSubModel?pSubModel->pName:NULL);};
//void __fastcall SetRotateAnim(vector3 vNewRotateAxis, double fNewDesiredAngle, double fNewRotateSpeed, bool bResetAngle=false);
void __fastcall SetRotateAnim(vector3 vNewRotateAngles, double fNewRotateSpeed);
void __fastcall SetTranslateAnim(vector3 vNewTranslate, double fNewSpeed);
void __fastcall AnimSetVMD(double fNewSpeed);
void __fastcall PrepareModel();
void __fastcall UpdateModel();
void __fastcall UpdateModelIK();
bool __fastcall InMovement(); //czy w trakcie animacji?
double _fastcall AngleGet() {return vRotateAngles.z;}; //jednak ostatnia, T3D ma inny uk³ad
vector3 _fastcall TransGet() {return vector3(-vTranslation.x,vTranslation.z,vTranslation.y);}; //zmiana, bo T3D ma inny uk³ad
void __fastcall WillBeAnimated() {if (pSubModel) pSubModel->WillBeAnimated();};
void __fastcall EventAssign(TEvent *ev);
TEvent* __fastcall Event() {return evDone;};
};
class TAnimAdvanced
{//obiekt zaawansowanej animacji submodelu
public:
TAnimVocaloidFrame *pMovementData;
unsigned char *pVocaloidMotionData; //plik animacyjny dla egzemplarza (z eventu)
double fFrequency; //przeliczenie czasu rzeczywistego na klatki animacji
double fCurrent; //klatka animacji wyœwietlona w poprzedniej klatce renderingu
double fLast; //klatka koñcz¹ca animacjê
int iMovements;
__fastcall TAnimAdvanced();
__fastcall ~TAnimAdvanced();
int __fastcall SortByBone();
};
class TAnimModel
{//opakowanie modelu, okreœlaj¹ce stan egzemplarza
private:
TAnimContainer *pRoot; //pojemniki steruj¹ce, tylko dla aniomowanych submodeli
TModel3d *pModel;
double fBlinkTimer;
int iNumLights;
TSubModel *LightsOn[iMaxNumLights]; //Ra: te wskaŸniki powinny byæ w ramach TModel3d
TSubModel *LightsOff[iMaxNumLights];
vector3 vAngle; //bazowe obroty egzemplarza wzglêdem osi
int iTexAlpha; //¿eby nie sprawdzaæ za ka¿dym razem, dla 4 wymiennych tekstur
AnsiString asText; //tekst dla wyœwietlacza znakowego
TAnimAdvanced *pAdvanced;
void __fastcall Advanced();
TLightState lsLights[iMaxNumLights];
float fDark; //poziom zapalanie œwiat³a (powinno byæ chyba powi¹zane z danym œwiat³em?)
float fOnTime,fOffTime; //by³y sta³ymi, teraz mog¹ byæ zmienne dla ka¿dego egzemplarza
private:
void __fastcall RaAnimate(); //przeliczenie animacji egzemplarza
void __fastcall RaPrepare(); //ustawienie animacji egzemplarza na wzorcu
public:
GLuint ReplacableSkinId[5]; //McZapkie-020802: zmienialne skory
static TAnimContainer *acAnimList; //lista animacji z eventem, które musz¹ byæ przeliczane równie¿ bez wyœwietlania
__fastcall TAnimModel();
__fastcall ~TAnimModel();
bool __fastcall Init(TModel3d *pNewModel);
bool __fastcall Init(AnsiString asName,AnsiString asReplacableTexture);
bool __fastcall Load(cParser *parser, bool ter=false);
TAnimContainer* __fastcall AddContainer(char *pName);
TAnimContainer* __fastcall GetContainer(char *pName);
void __fastcall RenderDL(vector3 pPosition=vector3(0,0,0),double fAngle=0);
void __fastcall RenderAlphaDL(vector3 pPosition=vector3(0,0,0),double fAngle=0);
void __fastcall RenderVBO(vector3 pPosition=vector3(0,0,0),double fAngle=0);
void __fastcall RenderAlphaVBO(vector3 pPosition=vector3(0,0,0),double fAngle=0);
void __fastcall RenderDL(vector3* vPosition);
void __fastcall RenderAlphaDL(vector3* vPosition);
void __fastcall RenderVBO(vector3* vPosition);
void __fastcall RenderAlphaVBO(vector3* vPosition);
int __fastcall Flags();
void __fastcall RaAnglesSet(double a,double b,double c)
{vAngle.x=a; vAngle.y=b; vAngle.z=c;};
bool __fastcall TerrainLoaded();
int __fastcall TerrainCount();
TSubModel* __fastcall TerrainSquare(int n);
void __fastcall TerrainRenderVBO(int n);
void __fastcall AnimationVND(void* pData, double a, double b, double c, double d);
void __fastcall LightSet(int n,float v);
static void __fastcall AnimUpdate(double dt);
};
TAnimContainer *TAnimModel::acAnimList=NULL;
//---------------------------------------------------------------------------
#endif

70
Button.cpp Normal file
View File

@@ -0,0 +1,70 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Button.h"
#include "Console.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TButton::TButton()
{
iFeedbackBit=0;
Clear();
};
__fastcall TButton::~TButton()
{
};
void __fastcall TButton::Clear(int i)
{
pModelOn=NULL;
pModelOff=NULL;
bOn=false;
if (i>=0) FeedbackBitSet(i);
Update(); //kasowanie bitu Feedback, o ile jakiœ ustawiony
};
void __fastcall TButton::Init(AnsiString asName,TModel3d *pModel,bool bNewOn)
{
if (!pModel) return; //nie ma w czym szukaæ
pModelOn=pModel->GetFromName(AnsiString(asName+"_on").c_str());
pModelOff=pModel->GetFromName(AnsiString(asName+"_off").c_str());
bOn=bNewOn;
Update();
};
void __fastcall TButton::Load(TQueryParserComp *Parser,TModel3d *pModel1,TModel3d *pModel2)
{
AnsiString str=Parser->GetNextSymbol().LowerCase();
if (pModel1)
{//poszukiwanie submodeli w modelu
Init(str,pModel1,false);
if (pModel2)
if (!pModelOn&&!pModelOff)
Init(str,pModel2,false); //mo¿e w drugim bêdzie (jak nie w kabinie, to w zewnêtrznym)
}
else
{
pModelOn=NULL;
pModelOff=NULL;
}
};
void __fastcall TButton::Update()
{
if (pModelOn) pModelOn->iVisible=bOn;
if (pModelOff) pModelOff->iVisible=!bOn;
if (iFeedbackBit) //je¿eli generuje informacjê zwrotn¹
{if (bOn) //zapalenie
Console::BitsSet(iFeedbackBit);
else
Console::BitsClear(iFeedbackBit);
}
};

31
Button.h Normal file
View File

@@ -0,0 +1,31 @@
//---------------------------------------------------------------------------
#ifndef ButtonH
#define ButtonH
#include "Model3d.h"
#include "QueryParserComp.hpp"
class TButton
{//animacja dwustanowa, w³¹cza jeden z dwóch submodeli (jednego z nich mo¿e nie byæ)
private:
TSubModel *pModelOn,*pModelOff; //submodel dla stanu za³¹czonego i wy³¹czonego
bool bOn;
int iFeedbackBit; //Ra: bit informacji zwrotnej, do wyprowadzenia na pulpit
void __fastcall Update();
public:
__fastcall TButton();
__fastcall ~TButton();
void __fastcall Clear(int i=-1);
inline void FeedbackBitSet(int i) {iFeedbackBit=1<<i;};
inline void Turn(bool to) { bOn=to; Update(); };
inline void TurnOn() { bOn=true; Update(); };
inline void TurnOff() { bOn=false; Update(); };
inline void Switch() { bOn=!bOn; Update(); };
inline bool Active() { return (pModelOn)||(pModelOff);};
void __fastcall Init(AnsiString asName,TModel3d *pModel,bool bNewOn=false);
void __fastcall Load(TQueryParserComp *Parser,TModel3d *pModel1,TModel3d *pModel2=NULL);
};
//---------------------------------------------------------------------------
#endif

196
Camera.cpp Normal file
View File

@@ -0,0 +1,196 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#include "opengl/glew.h"
#include "opengl/glut.h"
#pragma hdrstop
#include "Camera.h"
#include "Usefull.h"
#include "Globals.h"
#include "Timer.h"
#include "mover.h"
#include "Console.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//TViewPyramid TCamera::OrgViewPyramid;
//={vector3(-1,1,1),vector3(1,1,1),vector3(-1,-1,1),vector3(1,-1,1),vector3(0,0,0)};
const vector3 OrgCrossPos= vector3(0,-10,0);
void __fastcall TCamera::Init(vector3 NPos, vector3 NAngle)
{
pOffset= vector3(-0.0,0,0);
vUp= vector3(0,1,0);
// pOffset= vector3(-0.8,0,0);
CrossPos= OrgCrossPos;
CrossDist= 10;
Velocity=vector3(0,0,0);
OldVelocity= vector3(0,0,0);
Pitch= NAngle.x;
Yaw= NAngle.y;
Roll= NAngle.z;
Pos= NPos;
// Type= tp_Follow;
Type= (Global::bFreeFly ? tp_Free : tp_Follow);
// Type= tp_Free;
};
void __fastcall TCamera::OnCursorMove(double x, double y)
{
//McZapkie-170402: zeby mysz dzialala zawsze if (Type==tp_Follow)
Pitch+=y;
Yaw+=-x;
if (Yaw>M_PI)
Yaw-=2*M_PI;
else if (Yaw<-M_PI)
Yaw+=2*M_PI;
if (Type==tp_Follow) //je¿eli jazda z pojazdem
{
Fix(Pitch,-M_PI_4,M_PI_4); //ograniczenie k¹ta spogl¹dania w dó³ i w górê
//Fix(Yaw,-M_PI,M_PI);
}
}
void __fastcall TCamera::Update()
{
//ABu: zmiana i uniezaleznienie predkosci od FPS
double a= (Console::Pressed(VK_SHIFT)?5.00:1.00);
if (Console::Pressed(VK_CONTROL))
a=a*100;
// OldVelocity=Velocity;
if (FreeFlyModeFlag==true)
Type=tp_Free;
else
Type=tp_Follow;
if (Type==tp_Free)
{
if (Console::Pressed(Global::Keys[k_MechUp])) Velocity.y+=a;
if (Console::Pressed(Global::Keys[k_MechDown])) Velocity.y-=a;
//McZapkie-170402: zeby nie bylo konfliktow
/*
if (Console::Pressed(VkKeyScan('d')))
Velocity.x+= a*Timer::GetDeltaTime();
if (Console::Pressed(VkKeyScan('a')))
Velocity.x-= a*Timer::GetDeltaTime();
if (Console::Pressed(VkKeyScan('w')))
Velocity.z-= a*Timer::GetDeltaTime();
if (Console::Pressed(VkKeyScan('s')))
Velocity.z+= a*Timer::GetDeltaTime();
if (Console::Pressed(VK_NUMPAD4) || Console::Pressed(VK_NUMPAD7) || Console::Pressed(VK_NUMPAD1))
Yaw+= +1*M_PI*Timer::GetDeltaTime();
if (Console::Pressed(VK_NUMPAD6) || Console::Pressed(VK_NUMPAD9) || Console::Pressed(VK_NUMPAD3))
Yaw+= -1*M_PI*Timer::GetDeltaTime();
if (Pressed(VK_NUMPAD2) || Console::Pressed(VK_NUMPAD1) || Console::Pressed(VK_NUMPAD3))
Pitch+= -1*M_PI*Timer::GetDeltaTime();
if (Console::Pressed(VK_NUMPAD8) || Console::Pressed(VK_NUMPAD7) || Console::Pressed(VK_NUMPAD9))
Pitch+= +1*M_PI*Timer::GetDeltaTime();
if (Console::Pressed(VkKeyScan('.')))
Roll+= -1*M_PI*Timer::GetDeltaTime();
if (Console::Pressed(VkKeyScan(',')))
Roll+= +1*M_PI*Timer::GetDeltaTime();
if (Console::Pressed(VK_NUMPAD5))
Pitch=Roll= 0.0f;
*/
//McZapkie-170402: poruszanie i rozgladanie we free takie samo jak w follow
if (Console::Pressed(Global::Keys[k_MechRight])) Velocity.x+=a;
if (Console::Pressed(Global::Keys[k_MechLeft])) Velocity.x-=a;
if (Console::Pressed(Global::Keys[k_MechForward])) Velocity.z-=a;
if (Console::Pressed(Global::Keys[k_MechBackward])) Velocity.z+=a;
//gora-dol
//if (Console::Pressed(VK_NUMPAD9)) Pos.y+=0.1;
//if (Console::Pressed(VK_NUMPAD3)) Pos.y-=0.1;
//McZapkie: zeby nie hustalo przy malym FPS:
// Velocity= (Velocity+OldVelocity)/2;
// matrix4x4 mat;
vector3 Vec=Velocity;
Vec.RotateY(Yaw);
Pos=Pos+Vec*Timer::GetDeltaRenderTime(); //czas bez pauzy
Velocity=Velocity/2; //p³ynne hamowanie ruchu
// double tmp= 10*DeltaTime;
// Velocity+= -Velocity*10 * Timer::GetDeltaTime();//( tmp<1 ? tmp : 1 );
// Type= tp_Free;
}
}
vector3 __fastcall TCamera::GetDirection()
{
matrix4x4 mat;
vector3 Vec;
Vec= vector3(0,0,1);
Vec.RotateY(Yaw);
return (Normalize(Vec));
}
//bool __fastcall TCamera::GetMatrix(matrix4x4 &Matrix)
bool __fastcall TCamera::SetMatrix()
{
glRotated(-Roll*180.0f/M_PI,0,0,1); //po wy³¹czeniu tego krêci siê pojazd, a sceneria nie
glRotated(-Pitch*180.0f/M_PI,1,0,0);
glRotated(-Yaw*180.0f/M_PI,0,1,0); //w zewnêtrznym widoku: kierunek patrzenia
if (Type==tp_Follow)
{
// gluLookAt(Pos.x+pOffset.x,Pos.y+pOffset.y,Pos.z+pOffset.z,
// LookAt.x+pOffset.x,LookAt.y+pOffset.y,LookAt.z+pOffset.z,vUp.x,vUp.y,vUp.z);
// gluLookAt(Pos.x+pOffset.x,Pos.y+pOffset.y,Pos.z+pOffset.z,
// LookAt.x+pOffset.x,LookAt.y+pOffset.y,LookAt.z+pOffset.z,vUp.x,vUp.y,vUp.z);
gluLookAt(Pos.x,Pos.y,Pos.z,LookAt.x,LookAt.y,LookAt.z,vUp.x,vUp.y,vUp.z); //Ra: pOffset is zero
// gluLookAt(Pos.x,Pos.y,Pos.z,Pos.x+Velocity.x,Pos.y+Velocity.y,Pos.z+Velocity.z,0,1,0);
// return true;
}
if (Type==tp_Satelite)
Pitch= M_PI*0.5;
if (Type!=tp_Follow)
{
glTranslated(-Pos.x,-Pos.y,-Pos.z); //nie zmienia kierunku patrzenia
}
Global::SetCameraPosition(Pos); //by³o +pOffset
return true;
}
void __fastcall TCamera::SetCabMatrix(vector3 &p)
{//ustawienie widoku z kamery bez przesuniêcia robionego przez OpenGL - nie powinno tak trz¹œæ
glRotated(-Roll*180.0f/M_PI,0,0,1);
glRotated(-Pitch*180.0f/M_PI,1,0,0);
glRotated(-Yaw*180.0f/M_PI,0,1,0); //w zewnêtrznym widoku: kierunek patrzenia
if (Type==tp_Follow)
gluLookAt(Pos.x-p.x,Pos.y-p.y,Pos.z-p.z,LookAt.x-p.x,LookAt.y-p.y,LookAt.z-p.z,vUp.x,vUp.y,vUp.z); //Ra: pOffset is zero
}
void __fastcall TCamera::RaLook()
{//zmiana kierunku patrzenia - przelicza Yaw
vector3 where=LookAt-Pos+vector3(0,3,0); //trochê w górê od szyn
if ((where.x!=0.0)||(where.z!=0.0))
Yaw=atan2(-where.x,-where.z); //k¹t horyzontalny
double l=Length3(where);
if (l>0.0)
Pitch=asin(where.y/l); //k¹t w pionie
};
void __fastcall TCamera::Stop()
{//wy³¹cznie bezw³adnego ruchu po powrocie do kabiny
Type=tp_Follow;
Velocity=vector3(0,0,0);
};

47
Camera.h Normal file
View File

@@ -0,0 +1,47 @@
//---------------------------------------------------------------------------
#ifndef CameraH
#define CameraH
#include "dumb3d.h"
using namespace Math3D;
//---------------------------------------------------------------------------
enum TCameraType
{//tryby pracy kamery
tp_Follow, //jazda z pojazdem
tp_Free, //stoi na scenerii
tp_Satelite //widok z góry (nie używany)
};
class TCamera
{
private:
vector3 pOffset; //nie używane (zerowe)
public: //McZapkie: potrzebuje do kiwania na boki
double Pitch;
double Yaw; //w środku: 0=do przodu; na zewnątrz: 0=na południe
double Roll;
TCameraType Type;
vector3 Pos; //współrzędne obserwatora
vector3 LookAt; //współrzędne punktu, na który ma patrzeć
vector3 vUp;
vector3 Velocity;
vector3 OldVelocity; //lepiej usredniac zeby nie bylo rozbiezne przy malym FPS
vector3 CrossPos;
double CrossDist;
void __fastcall Init(vector3 NPos, vector3 NAngle);
void __fastcall Reset() { Pitch=Yaw=Roll= 0; };
void __fastcall OnCursorMove(double x, double y);
void __fastcall Update();
vector3 __fastcall GetDirection();
//vector3 inline __fastcall GetCrossPos() { return Pos+GetDirection()*CrossDist+CrossPos; };
bool __fastcall SetMatrix();
void __fastcall SetCabMatrix(vector3 &p);
void __fastcall RaLook();
void __fastcall Stop();
//bool __fastcall GetMatrix(matrix4x4 &Matrix);
vector3 PtNext, PtPrev;
};
#endif

10
Classes.cpp Normal file
View File

@@ -0,0 +1,10 @@
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Classes.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

54
Classes.h Normal file
View File

@@ -0,0 +1,54 @@
//---------------------------------------------------------------------------
#ifndef ClassesH
#define ClassesH
//---------------------------------------------------------------------------
//Ra: zestaw klas do robienia wskaźników, aby uporządkować nagłówki
//---------------------------------------------------------------------------
class TTrack; //odcinek trajektorii
class TEvent;
class TTrain; //pojazd sterowany
class TDynamicObject; //pojazd w scenerii
class TGroundNode; //statyczny obiekt scenerii
class TAnimModel; //opakowanie egzemplarz modelu
class TAnimContainer; //fragment opakowania egzemplarza modelu
//class TModel3d; //siatka modelu wspólna dla egzemplarzy
class TSubModel; //fragment modelu (tu do wyświetlania terenu)
class TMemCell; //komórka pamięci
class cParser;
class TRealSound; //dźwięk ze współrzędnymi XYZ
class TTextSound; //dźwięk ze stenogramem
class TEventLauncher;
class TTraction; //drut
class TTractionPowerSource; //zasilanie drutów
class TMoverParameters;
namespace _mover
{
class TLocation;
class TRotation;
};
namespace Mtable
{
class TTrainParameters; //rozkład jazdy
};
class TController; //obiekt sterujący pociągiem (AI)
class TNames; //obiekt sortujący nazwy
typedef enum
{//binarne odpowiedniki komend w komórce pamięci
cm_Unknown, //ciąg nierozpoznany (nie jest komendą)
cm_Ready, //W4 zezwala na odjazd, ale semafor może zatrzymać
cm_SetVelocity,
cm_ShuntVelocity,
cm_SetProximityVelocity,
cm_ChangeDirection,
cm_PassengerStopPoint,
cm_OutsideStation,
cm_Shunt,
cm_Command //komenda pobierana z komórki
} TCommandType;
#endif

347
Console.cpp Normal file
View File

@@ -0,0 +1,347 @@
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Console.h"
#include "Globals.h"
#include "Logs.h"
#include "PoKeys55.h"
#include "LPT.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//Ra: klasa statyczna gromadząca sygnały sterujące oraz informacje zwrotne
//Ra: stan wejścia zmieniany klawiaturą albo dedykowanym urządzeniem
//Ra: stan wyjścia zmieniany przez symulację (mierniki, kontrolki)
/*******************************
Do klawisza klawiatury przypisana jest maska bitowa oraz numer wejścia.
Naciśnięcie klawisza powoduje wywołanie procedury ustawienia bitu o podanej
masce na podanym wejściu. Zwonienie klawisza analogicznie wywołuje zerowanie
bitu wg maski. Zasadniczo w masce ustawiony jest jeden bit, ale w razie
potrzeby może być ich więcej.
Oddzielne wejścia są wprowadzone po to, by można było używać więcej niż 32
bity do sterowania. Podział na wejścia jest również ze względów organizacyjnych,
np. sterowanie światłami może mieć oddzielny numer wejścia niż przełączanie
radia, ponieważ nie ma potrzeby ich uzależniać (tzn. badać wspólną maskę bitową).
Do każdego wejścia podpięty jest skrypt binarny, charakterystyczny dla danej
konstrukcji pojazdu. Sprawdza on zależności (w tym uszkodzenia) za pomocą
operacji logicznych na maskach bitowych. Do każdego wejścia jest przypisana
jedna, oddzielna maska 32 bit, ale w razie potrzeby istnieje też możliwość
korzystania z masek innych wejść. Skrypt może też wysyłać maski na inne wejścia,
ale należy unikać rekurencji.
Definiowanie wejść oraz przeznaczenia ich masek jest w gestii konstruktora
skryptu. Każdy pojazd może mieć inny schemat wejść i masek, ale w miarę możliwości
należy dążyć do unifikacji. Skrypty mogą również używać dodatkowych masek bitowych.
Maski bitowe odpowiadają stanom przełączników, czujników, styczników itd.
Działanie jest następujące:
- na klawiaturze konsoli naciskany jest przycisk
- naciśnięcie przycisku zamieniane jest na maskę bitową oraz numer wejścia
- wywoływany jest skrypt danego wejścia z ową maską
- skrypt sprawdza zależności i np. modyfikuje własności fizyki albo inne maski
- ewentualnie do wyzwalacza czasowego dodana jest maska i numer wejścia
/*******************************/
/* //kod do przetrawienia:
//aby się nie włączacz wygaszacz ekranu, co jakiś czas naciska się wirtualnie ScrollLock
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
private static void PressScrollLock()
{//przyciska i zwalnia ScrollLock
const byte vkScroll = 0x91;
const byte keyeventfKeyup = 0x2;
keybd_event(vkScroll, 0x45, 0, (UIntPtr)0);
keybd_event(vkScroll, 0x45, keyeventfKeyup, (UIntPtr)0);
};
[DllImport("user32.dll")]
private static extern bool SystemParametersInfo(int uAction,int uParam,int &lpvParam,int flags);
public static Int32 GetScreenSaverTimeout()
{
Int32 value=0;
SystemParametersInfo(14,0,&value,0);
return value;
};
*/
//Ra: do poprawienia
void SetLedState(char Code,bool bOn)
{//Ra: bajer do migania LED-ami w klawiaturze
if (Win32Platform==VER_PLATFORM_WIN32_NT)
{
//WriteLog(AnsiString(int(GetAsyncKeyState(Code))));
if (bool(GetAsyncKeyState(Code))!=bOn)
{
keybd_event(Code,MapVirtualKey(Code,0),KEYEVENTF_EXTENDEDKEY,0);
keybd_event(Code,MapVirtualKey(Code,0),KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP,0);
}
}
else
{
TKeyboardState KBState;
GetKeyboardState(KBState);
KBState[Code]=bOn?1:0;
SetKeyboardState(KBState);
};
};
//---------------------------------------------------------------------------
int Console::iBits=0; //zmienna statyczna - obiekt Console jest jednen wspólny
int Console::iMode=0;
int Console::iConfig=0;
TPoKeys55 *Console::PoKeys55[2]={NULL,NULL};
TLPT *Console::LPT=NULL;
int Console::iSwitch[8]; //bistabilne w kabinie, załączane z [Shift], wyłączane bez
int Console::iButton[8]; //monostabilne w kabinie, załączane podczas trzymania klawisza
__fastcall Console::Console()
{
PoKeys55[0]=PoKeys55[1]=NULL;
for (int i=0;i<8;++i)
{//zerowanie przełączników
iSwitch[i]=0; //bity 0..127 - bez [Ctrl], 128..255 - z [Ctrl]
iButton[i]=0; //bity 0..127 - bez [Shift], 128..255 - z [Shift]
}
};
__fastcall Console::~Console()
{
delete PoKeys55[0];
delete PoKeys55[1];
};
void __fastcall Console::ModeSet(int m,int h)
{//ustawienie trybu pracy
iMode=m;
iConfig=h;
};
int __fastcall Console::On()
{//załączenie konsoli (np. nawiązanie komunikacji)
iSwitch[0]=iSwitch[1]=iSwitch[2]=iSwitch[3]=0; //bity 0..127 - bez [Ctrl]
iSwitch[4]=iSwitch[5]=iSwitch[6]=iSwitch[7]=0; //bity 128..255 - z [Ctrl]
switch (iMode)
{case 1: //kontrolki klawiatury
case 2: //kontrolki klawiatury
iConfig=0; //licznik użycia Scroll Lock
break;
case 3: //LPT
LPT=new TLPT(); //otwarcie inpout32.dll
if (LPT?LPT->Connect(iConfig):false)
{//wysłać 0?
BitsUpdate(-1); //aktualizacjia stanów, bo przy wczytywaniu mogło być nieaktywne
WriteLog("Feedback Mode 3: InpOut32.dll OK");
}
else
{//połączenie nie wyszło, ma być NULL
delete LPT;
LPT=NULL;
}
break;
case 4: //PoKeys
PoKeys55[0]=new TPoKeys55();
if (PoKeys55[0]?PoKeys55[0]->Connect():false)
{WriteLog("Found "+PoKeys55[0]->Version());
BitsUpdate(-1); //aktualizacjia stanów, bo przy wczytywaniu mogło być nieaktywne
}
else
{//połączenie nie wyszło, ma być NULL
delete PoKeys55[0];
PoKeys55[0]=NULL;
}
break;
}
return 0;
};
void __fastcall Console::Off()
{//wyłączenie informacji zwrotnych (reset pulpitu)
BitsClear(-1);
if ((iMode==1)||(iMode==2))
if (iConfig&1) //licznik użycia Scroll Lock
{//bez sensu to jest, ale mi się samo włącza
SetLedState(VK_SCROLL,true); //przyciśnięty
SetLedState(VK_SCROLL,false); //zwolniony
}
delete PoKeys55[0]; PoKeys55[0]=NULL;
delete PoKeys55[1]; PoKeys55[1]=NULL;
delete LPT; LPT=NULL;
};
void __fastcall Console::BitsSet(int mask,int entry)
{//ustawienie bitów o podanej masce (mask) na wejściu (entry)
if ((iBits&mask)!=mask) //jeżeli zmiana
{int old=iBits; //poprzednie stany
iBits|=mask;
BitsUpdate(old^iBits); //1 dla bitów zmienionych
}
};
void __fastcall Console::BitsClear(int mask,int entry)
{//zerowanie bitów o podanej masce (mask) na wejściu (entry)
if (iBits&mask) //jeżeli zmiana
{int old=iBits; //poprzednie stany
iBits&=~mask;
BitsUpdate(old^iBits); //1 dla bitów zmienionych
}
};
void __fastcall Console::BitsUpdate(int mask)
{//aktualizacja stanu interfejsu informacji zwrotnej; (mask) - zakres zmienianych bitów
switch (iMode)
{case 1: //sterowanie światełkami klawiatury: CA/SHP+opory
if (mask&3) //gdy SHP albo CA
SetLedState(VK_CAPITAL,iBits&3);
if (mask&4) //gdy jazda na oporach
{//Scroll Lock ma jakoś dziwnie... zmiana stanu na przeciwny
SetLedState(VK_SCROLL,true); //przyciśnięty
SetLedState(VK_SCROLL,false); //zwolniony
++iConfig; //licznik użycia Scroll Lock
}
break;
case 2: //sterowanie światełkami klawiatury: CA+SHP
if (mask&2) //gdy CA
SetLedState(VK_CAPITAL,iBits&2);
if (mask&1) //gdy SHP
{//Scroll Lock ma jakoś dziwnie... zmiana stanu na przeciwny
SetLedState(VK_SCROLL,true); //przyciśnięty
SetLedState(VK_SCROLL,false); //zwolniony
++iConfig; //licznik użycia Scroll Lock
}
break;
case 3: //LPT Marcela z modyfikacją (jazda na oporach zamiast brzęczyka)
if (LPT)
LPT->Out(iBits);
break;
case 4: //PoKeys55 wg Marcela - wersja druga z końca 2012
if (PoKeys55[0])
{//pewnie trzeba będzie to dodatkowo buforować i oczekiwać na potwierdzenie
if (mask&0x0001) //b0 gdy SHP
PoKeys55[0]->Write(0x40,23-1,iBits&0x0001?1:0);
if (mask&0x0002) //b1 gdy zmieniony CA
PoKeys55[0]->Write(0x40,24-1,iBits&0x0002?1:0);
if (mask&0x0004) //b2 gdy jazda na oporach
PoKeys55[0]->Write(0x40,32-1,iBits&0x0004?1:0);
if (mask&0x0008) //b3 Lampka WS (wyłącznika szybkiego)
PoKeys55[0]->Write(0x40,25-1,iBits&0x0008?1:0);
if (mask&0x0010) //b4 Lampka przekaźnika nadmiarowego silników trakcyjnych
PoKeys55[0]->Write(0x40,27-1,iBits&0x0010?1:0);
if (mask&0x0020) //b5 Lampka styczników liniowych
PoKeys55[0]->Write(0x40,29-1,iBits&0x0020?1:0);
if (mask&0x0040) //b6 Lampka poślizgu
PoKeys55[0]->Write(0x40,30-1,iBits&0x0040?1:0);
if (mask&0x0080) //b7 Lampka "przetwornicy"
PoKeys55[0]->Write(0x40,28-1,iBits&0x0080?1:0);
if (mask&0x0100) //b8 Kontrolka przekaźnika nadmiarowego sprężarki
PoKeys55[0]->Write(0x40,33-1,iBits&0x0100?1:0);
if (mask&0x0200) //b9 Kontrolka sygnalizacji wentylatorów i oporów
PoKeys55[0]->Write(0x40,26-1,iBits&0x0200?1:0);
if (mask&0x0400) //b10 Kontrolka wysokiego rozruchu
PoKeys55[0]->Write(0x40,31-1,iBits&0x0400?1:0);
if (mask&0x0800) //b11 Kontrolka ogrzewania pociągu
PoKeys55[0]->Write(0x40,34-1,iBits&0x0800?1:0);
if (mask&0x1000) //b12 Ciśnienie w cylindrach do odbijania w haslerze
PoKeys55[0]->Write(0x40,52-1,iBits&0x1000?1:0);
if (mask&0x2000) //b13 Prąd na silnikach do odbijania w haslerze
PoKeys55[0]->Write(0x40,53-1,iBits&0x2000?1:0);
}
break;
}
};
bool __fastcall Console::Pressed(int x)
{//na razie tak - czyta się tylko klawiatura
return Global::bActive&&(GetKeyState(x)<0);
};
void __fastcall Console::ValueSet(int x,double y)
{//ustawienie wartości (y) na kanale analogowym (x)
if (iMode==4)
if (PoKeys55[0])
{
PoKeys55[0]->PWM(x,(((Global::fCalibrateOut[x][3]*y)+Global::fCalibrateOut[x][2])*y+Global::fCalibrateOut[x][1])*y+Global::fCalibrateOut[x][0]); //zakres <0;1>
}
};
void __fastcall Console::Update()
{//funkcja powinna być wywoływana regularnie, np. raz w każdej ramce ekranowej
if (iMode==4)
if (PoKeys55[0])
if (PoKeys55[0]->Update((Global::iPause&8)>0))
{//wykrycie przestawionych przełączników?
Global::iPause&=~8;
}
else
{//błąd komunikacji - zapauzować symulację?
if (!(Global::iPause&8)) //jeśli jeszcze nie oflagowana
Global::iTextMode=VK_F1; //pokazanie czasu/pauzy
Global::iPause|=8; //tak???
PoKeys55[0]->Connect(); //próba ponownego podłączenia
}
};
float __fastcall Console::AnalogGet(int x)
{//pobranie wartości analogowej
if (iMode==4)
if (PoKeys55[0])
return PoKeys55[0]->fAnalog[x];
return -1.0;
};
unsigned char __fastcall Console::DigitalGet(int x)
{//pobranie wartości cyfrowej
if (iMode==4)
if (PoKeys55[0])
return PoKeys55[0]->iInputs[x];
return 0;
};
void __fastcall Console::OnKeyDown(int k)
{//naciśnięcie klawisza z powoduje wyłączenie, a
if (k&0x10000) //jeśli [Shift]
{//ustawienie bitu w tabeli przełączników bistabilnych
if (k&0x20000) //jeśli [Ctrl], to zestaw dodatkowy
iSwitch[4+(char(k)>>5)]|=1<<(k&31); //załącz bistabliny dodatkowy
else
{//z [Shift] włączenie bitu bistabilnego i dodatkowego monostabilnego
iSwitch[char(k)>>5]|=1<<(k&31); //załącz bistabliny podstawowy
iButton[4+(char(k)>>5)]|=(1<<(k&31)); //załącz monostabilny dodatkowy
}
}
else
{//zerowanie bitu w tabeli przełączników bistabilnych
if (k&0x20000) //jeśli [Ctrl], to zestaw dodatkowy
iSwitch[4+(char(k)>>5)]&=~(1<<(k&31)); //wyłącz bistabilny dodatkowy
else
{iSwitch[char(k)>>5]&=~(1<<(k&31)); //wyłącz bistabilny podstawowy
iButton[char(k)>>5]|=1<<(k&31); //załącz monostabilny podstawowy
}
}
};
void __fastcall Console::OnKeyUp(int k)
{//puszczenie klawisza w zasadzie nie ma znaczenia dla iSwitch, ale zeruje iButton
if ((k&0x20000)==0) //monostabilne tylko bez [Ctrl]
if (k&0x10000) //jeśli [Shift]
iButton[4+(char(k)>>5)]&=~(1<<(k&31)); //wyłącz monostabilny dodatkowy
else
iButton[char(k)>>5]&=~(1<<(k&31)); //wyłącz monostabilny podstawowy
};
int __fastcall Console::KeyDownConvert(int k)
{
return int(ktTable[k&0x3FF].iDown);
};
int __fastcall Console::KeyUpConvert(int k)
{
return int(ktTable[k&0x3FF].iUp);
};

55
Console.h Normal file
View File

@@ -0,0 +1,55 @@
//---------------------------------------------------------------------------
#ifndef ConsoleH
#define ConsoleH
//---------------------------------------------------------------------------
class TConsoleDevice; //urządzenie podłączalne za pomocą DLL
class TPoKeys55;
class TLPT;
//klasy konwersji znaków wprowadzanych z klawiatury
class TKeyTrans
{//przekodowanie kodu naciśnięcia i zwolnienia klawisza
public:
short int iDown,iUp;
};
class Console
{//Ra: klasa statyczna gromadząca sygnały sterujące oraz informacje zwrotne
//Ra: stan wejścia zmieniany klawiaturą albo dedykowanym urządzeniem
//Ra: stan wyjścia zmieniany przez symulację (mierniki, kontrolki)
private:
static int iMode; //tryb pracy
static int iConfig; //dodatkowa informacja o sprzęcie (np. numer LPT)
static int iBits; //podstawowy zestaw lampek
static TPoKeys55 *PoKeys55[2]; //może ich być kilka
static TLPT *LPT;
static void __fastcall BitsUpdate(int mask);
//zmienne dla trybu "jednokabinowego", potrzebne do współpracy z pulpitem (PoKeys)
//używając klawiatury, każdy pojazd powinien mieć własny stan przełączników
//bazowym sterowaniem jest wirtualny strumień klawiatury
//przy zmianie kabiny z PoKeys, do kabiny są wysyłane stany tych przycisków
static int iSwitch[8]; //bistabilne w kabinie, załączane z [Shift], wyłączane bez
static int iButton[8]; //monostabilne w kabinie, załączane podczas trzymania klawisza
static TKeyTrans ktTable[4*256]; //tabela wczesnej konwersji klawiatury
public:
__fastcall Console();
__fastcall ~Console();
static void __fastcall ModeSet(int m,int h=0);
static void __fastcall BitsSet(int mask,int entry=0);
static void __fastcall BitsClear(int mask,int entry=0);
static int __fastcall On();
static void __fastcall Off();
static bool __fastcall Pressed(int x);
static void __fastcall ValueSet(int x,double y);
static void __fastcall Update();
static float __fastcall AnalogGet(int x);
static unsigned char __fastcall DigitalGet(int x);
static void __fastcall OnKeyDown(int k);
static void __fastcall OnKeyUp(int k);
static int __fastcall KeyDownConvert(int k);
static int __fastcall KeyUpConvert(int k);
};
#endif

46
Console/LPT.cpp Normal file
View File

@@ -0,0 +1,46 @@
//---------------------------------------------------------------------------
#include "LPT.h"
#include <windows.h>
//LPT na USB:
//USB\VID_067B&PID_2305&REV_0200
//{9d7debbc-c85d-11d1-9eb4-006008c3a19a}
//USB\VID_067B&PID_2305\5&1E41AFF0&0&2
//IEEE-1284 Controller
HINSTANCE hDLL;
typedef USHORT (__stdcall *InPortType)(USHORT BasePort);
typedef void (__stdcall *OutPortType)(USHORT BasePort, USHORT value);
InPortType InPort;
OutPortType OutPort;
bool __fastcall TLPT::Connect(int port)
{
//ladowanie dll-ki
hDLL=LoadLibrary("inpout32.dll");
if (hDLL)
{
InPort=(InPortType)GetProcAddress(hDLL,"Inp32");
OutPort=(OutPortType)GetProcAddress(hDLL,"Out32");
}
else
return false; //MessageBox(NULL,"ERROR","B³¹d przy ³adowaniu pliku",MB_OK);
address=port; //&0xFFFFFC; //ostatnie 2 bity maj¹ byæ zerowe -> a niech sobie OUT-uj¹, gdzie chc¹
switch (address) //nie dotyczy 0x3BC
{case 0x0378:
case 0x0278:
OutPort(address+0x402,0); //SPP, czyli jednokierunkowe wyjœcie
break;
case 0xBC00:
case 0xBD00:
OutPort(address+0x006,0); //0xBC06? czysta improwizacja
}
return bool(OutPort);
};
void __fastcall TLPT::Out(int x)
{//wys³anie bajtu do portu
OutPort(address,x);
};

15
Console/LPT.h Normal file
View File

@@ -0,0 +1,15 @@
//---------------------------------------------------------------------------
#ifndef LPTH
#define LPTH
//---------------------------------------------------------------------------
class TLPT
{
private:
int address;
public:
bool __fastcall Connect(int port);
void __fastcall Out(int x);
};
#endif

316
Console/PoKeys55.cpp Normal file
View File

@@ -0,0 +1,316 @@
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <setupapi.h>
#include "PoKeys55.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//HIDscaner: http://forum.simflight.com/topic/68257-latest-lua-package-for-fsuipc-and-wideclient/
//#define MY_DEVICE_ID "Vid_04d8&Pid_003F"
//#define MY_DEVICE_ID "Vid_1dc3&Pid_1001&Rev_1000&MI_01"
//HID\Vid_1dc3&Pid_1001&Rev_1000&MI_01 - MI_01 to jest interfejs komunikacyjny (00-joystick, 02-klawiatura)
HANDLE WriteHandle=INVALID_HANDLE_VALUE;
HANDLE ReadHandle =INVALID_HANDLE_VALUE;
//GUID InterfaceClassGuid={0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30};
//{4d1e55b2-f16f-11cf-88cb-001111000030}
__fastcall TPoKeys55::TPoKeys55()
{
cRequest=0;
iPWMbits=1;
iFaza=0;
iLastCommand=0;
fAnalog[0]=fAnalog[1]=fAnalog[2]=fAnalog[3]=fAnalog[4]=fAnalog[5]=fAnalog[6]=-1.0;
iPWM[0]=iPWM[1]=iPWM[2]=iPWM[3]=iPWM[4]=iPWM[5]=iPWM[6]=0;
iPWM[7]=4096;
iInputs[0]=0; //czy normalnie s¹ w stanie wysokim?
iRepeats=0;
bNoError=true;
};
//---------------------------------------------------------------------------
__fastcall TPoKeys55::~TPoKeys55()
{
Close();
};
//---------------------------------------------------------------------------
bool __fastcall TPoKeys55::Close()
{//roz³¹czenie komunikacji
if (WriteHandle!=INVALID_HANDLE_VALUE)
CloseHandle(WriteHandle);
WriteHandle=INVALID_HANDLE_VALUE;
if (ReadHandle!=INVALID_HANDLE_VALUE)
CloseHandle(ReadHandle);
ReadHandle=INVALID_HANDLE_VALUE;
};
//---------------------------------------------------------------------------
bool __fastcall TPoKeys55::Connect()
{//Ra: to jest do wyczyszcznia z niepotrzebnych zmiennych i komunikatów
Close();
GUID InterfaceClassGuid={0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}; //wszystkie HID tak maj¹
HDEVINFO DeviceInfoTable;
PSP_DEVICE_INTERFACE_DATA InterfaceDataStructure=new SP_DEVICE_INTERFACE_DATA;
PSP_DEVICE_INTERFACE_DETAIL_DATA DetailedInterfaceDataStructure=new SP_DEVICE_INTERFACE_DETAIL_DATA;
SP_DEVINFO_DATA DevInfoData;
DWORD InterfaceIndex=0;
//DWORD StatusLastError=0;
DWORD dwRegType;
DWORD dwRegSize;
DWORD StructureSize=0;
PBYTE PropertyValueBuffer;
bool MatchFound;
DWORD ErrorStatus;
HDEVINFO hDevInfo;
String DeviceIDFromRegistry;
String DeviceIDToFind="Vid_1dc3&Pid_1001&Rev_1000&MI_01";
//First populate a list of plugged in devices (by specifying "DIGCF_PRESENT"), which are of the specified class GUID.
DeviceInfoTable=SetupDiGetClassDevs(&InterfaceClassGuid,NULL,NULL,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
//Now look through the list we just populated. We are trying to see if any of them match our device.
while (true)
{
InterfaceDataStructure->cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
if (SetupDiEnumDeviceInterfaces(DeviceInfoTable, NULL, &InterfaceClassGuid, InterfaceIndex, InterfaceDataStructure))
{
ErrorStatus=GetLastError();
if (ERROR_NO_MORE_ITEMS==ErrorStatus) //Did we reach the end of the list of matching devices in the DeviceInfoTable?
{//Cound not find the device. Must not have been attached.
SetupDiDestroyDeviceInfoList(DeviceInfoTable); //Clean up the old structure we no longer need.
//ShowMessage("Erreur: Sortie1");
return false;
}
}
else //Else some other kind of unknown error ocurred...
{
ErrorStatus=GetLastError();
SetupDiDestroyDeviceInfoList(DeviceInfoTable); //Clean up the old structure we no longer need.
//ShowMessage("Erreur: Sortie2");
return false;
}
//Now retrieve the hardware ID from the registry. The hardware ID contains the VID and PID, which we will then
//check to see if it is the correct device or not.
//Initialize an appropriate SP_DEVINFO_DATA structure. We need this structure for SetupDiGetDeviceRegistryProperty().
DevInfoData.cbSize=sizeof(SP_DEVINFO_DATA);
SetupDiEnumDeviceInfo(DeviceInfoTable,InterfaceIndex,&DevInfoData);
//First query for the size of the hardware ID, so we can know how big a buffer to allocate for the data.
SetupDiGetDeviceRegistryProperty(DeviceInfoTable,&DevInfoData,SPDRP_HARDWAREID,&dwRegType,NULL,0,&dwRegSize);
//Allocate a buffer for the hardware ID.
//PropertyValueBuffer=(BYTE*)malloc(dwRegSize);
PropertyValueBuffer=new char[dwRegSize];
if (PropertyValueBuffer==NULL) //if null,error,couldn't allocate enough memory
{//Can't really recover from this situation,just exit instead.
//ShowMessage("Allocation PropertyValueBuffer impossible");
SetupDiDestroyDeviceInfoList(DeviceInfoTable); //Clean up the old structure we no longer need.
return false;
}
//Retrieve the hardware IDs for the current device we are looking at. PropertyValueBuffer gets filled with a
//REG_MULTI_SZ (array of null terminated strings). To find a device,we only care about the very first string in the
//buffer,which will be the "device ID". The device ID is a string which contains the VID and PID,in the example
//format "Vid_04d8&Pid_003f".
SetupDiGetDeviceRegistryProperty(DeviceInfoTable,&DevInfoData,SPDRP_HARDWAREID,&dwRegType,PropertyValueBuffer,dwRegSize,NULL);
//Now check if the first string in the hardware ID matches the device ID of my USB device.
//ListBox1->Items->Add((char*)PropertyValueBuffer);
DeviceIDFromRegistry=StrPas((char*)PropertyValueBuffer);
//free(PropertyValueBuffer); //No longer need the PropertyValueBuffer,free the memory to prevent potential memory leaks
delete PropertyValueBuffer; //No longer need the PropertyValueBuffer,free the memory to prevent potential memory leaks
//Convert both strings to lower case. This makes the code more robust/portable accross OS Versions
DeviceIDFromRegistry=DeviceIDFromRegistry.LowerCase();
DeviceIDToFind=DeviceIDToFind.LowerCase();
//Now check if the hardware ID we are looking at contains the correct VID/PID
MatchFound=(DeviceIDFromRegistry.AnsiPos(DeviceIDToFind)>0);
if (MatchFound==true)
{
//Device must have been found. Open read and write handles. In order to do this,we will need the actual device path first.
//We can get the path by calling SetupDiGetDeviceInterfaceDetail(),however,we have to call this function twice: The first
//time to get the size of the required structure/buffer to hold the detailed interface data,then a second time to actually
//get the structure (after we have allocated enough memory for the structure.)
DetailedInterfaceDataStructure->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//First call populates "StructureSize" with the correct value
SetupDiGetDeviceInterfaceDetail(DeviceInfoTable,InterfaceDataStructure,NULL,NULL,&StructureSize,NULL);
DetailedInterfaceDataStructure=(PSP_DEVICE_INTERFACE_DETAIL_DATA)(malloc(StructureSize)); //Allocate enough memory
if (DetailedInterfaceDataStructure==NULL) //if null,error,couldn't allocate enough memory
{//Can't really recover from this situation,just exit instead.
SetupDiDestroyDeviceInfoList(DeviceInfoTable); //Clean up the old structure we no longer need.
return false;
}
DetailedInterfaceDataStructure->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//Now call SetupDiGetDeviceInterfaceDetail() a second time to receive the goods.
SetupDiGetDeviceInterfaceDetail(DeviceInfoTable,InterfaceDataStructure,DetailedInterfaceDataStructure,StructureSize,NULL,NULL);
//We now have the proper device path,and we can finally open read and write handles to the device.
//We store the handles in the global variables "WriteHandle" and "ReadHandle",which we will use later to actually communicate.
WriteHandle=CreateFile((DetailedInterfaceDataStructure->DevicePath),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,0);
ErrorStatus=GetLastError();
//if (ErrorStatus==ERROR_SUCCESS)
// ToggleLedBtn->Enabled=true;//Make button no longer greyed out
ReadHandle=CreateFile((DetailedInterfaceDataStructure->DevicePath),GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,0);
ErrorStatus=GetLastError();
if (ErrorStatus==ERROR_SUCCESS)
{
//GetPushbuttonState->Enabled=true;//Make button no longer greyed out
//StateLabel->Enabled=true;//Make label no longer greyed out
}
SetupDiDestroyDeviceInfoList(DeviceInfoTable); //Clean up the old structure we no longer need.
iRepeats=0; //nowe szanse na pod³¹czenie
return true;
}
InterfaceIndex++;
//Keep looping until we either find a device with matching VID and PID,or until we run out of items.
}//end of while(true)
//ShowMessage("Sortie");
return false;
}
//---------------------------------------------------------------------------
bool __fastcall TPoKeys55::Write(unsigned char c,unsigned char b3,unsigned char b4,unsigned char b5)
{
DWORD BytesWritten=0;
OutputBuffer[0]=0; //The first byte is the "Report ID" and does not get transmitted over the USB bus. Always set=0.
OutputBuffer[1]=0xBB; //0xBB - bajt rozpoznawczy dla PoKeys55
OutputBuffer[2]=iLastCommand=c; //operacja: 0x31: blokowy odczyt wejϾ
OutputBuffer[3]=b3; //np. numer pinu (o 1 mniej ni¿ numer na p³ytce)
OutputBuffer[4]=b4;
OutputBuffer[5]=b5;
OutputBuffer[6]=0;
OutputBuffer[7]=++cRequest; //numer ¿¹dania
OutputBuffer[8]=0;
for (int i=0;i<8;++i)
OutputBuffer[8]+=OutputBuffer[i]; //czy sumowaæ te¿ od 9 do 64?
//The basic Windows I/O functions WriteFile() and ReadFile() can be used to read and write to HID class USB devices
//(once we have the read and write handles to the device, which are obtained with CreateFile()).
//The following call to WriteFile() sends 64 bytes of data to the USB device.
WriteFile(WriteHandle,&OutputBuffer,65,&BytesWritten,0); //Blocking function, unless an "overlapped" structure is used
return (BytesWritten==65);
//Read(); //odczyt trzeba zrobiæ inaczej - w tym miejscu bêdzie za szybko i nic siê nie odczyta
}
//---------------------------------------------------------------------------
bool __fastcall TPoKeys55::Read()
{
DWORD BytesRead=0;
InputBuffer[0]=0; //The first byte is the "Report ID" and does not get transmitted over the USB bus. Always set=0.
//Now get the response packet from the firmware.
//The following call to ReadFIle() retrieves 64 bytes of data from the USB device.
ReadFile(ReadHandle,&InputBuffer,65,&BytesRead,0); //Blocking function,unless an "overlapped" structure is used
//InputPacketBuffer[0] is the report ID, which we don't care about.
//InputPacketBuffer[1] is an echo back of the command.
//InputPacketBuffer[2] contains the I/O port pin value for the pushbutton.
return (BytesRead==65)?InputBuffer[7]==cRequest:false;
}
//---------------------------------------------------------------------------
bool __fastcall TPoKeys55::ReadLoop(int i)
{//próbuje odczytaæ (i) razy
do
{if (Read()) return true;
Sleep(1); //trochê poczekaæ, a¿ odpowie
}
while (--i);
return false;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TPoKeys55::Version()
{//zwraca numer wersji, funkcja nieoptymalna czasowo (czeka na odpowiedŸ)
if (!WriteHandle) return "";
Write(0x00,0); //0x00 - Read serial number, version
if (ReadLoop(10))
{//3: serial MSB; 4: serial LSB; 5: software version (v(1+[4-7]).([0-3])); 6: revision number
AnsiString s="PoKeys55 #"+AnsiString((InputBuffer[3]<<8)+InputBuffer[4]);
s+=" v"+AnsiString(1+(InputBuffer[5]>>4))+"."+AnsiString(InputBuffer[5]&15)+"."+AnsiString(InputBuffer[6]);
/* //Ra: pozyskiwanie daty mo¿na sobie darowaæ, jest poniek¹d bez sensu
Write(0x04,0); //0x04 - Read build date: drugi argument zmieniaæ od 0 do 2, uzyskuj¹c kolejno po 4 znaki
if (ReadLoop(5))
{//2: 0x04; 3-6: char 1-4, 5-8, 9-11; (83-65-112-32-32-49-32-50-48-49-49-0=="Sep 1 2011")
s+=" ("+AnsiString((char*)InputBuffer+3,4);
Write(0x04,1); //0x04 - Read build date: drugi argument zmieniaæ od 0 do 2, uzyskuj¹c kolejno po 4 znaki
if (ReadLoop(5))
{s+=AnsiString((char*)InputBuffer+3,4);
Write(0x04,2); //0x04 - Read build date: drugi argument zmieniaæ od 0 do 2, uzyskuj¹c kolejno po 4 znaki
if (ReadLoop(5))
s+=AnsiString((char*)InputBuffer+3,3);
}
s+=")";
}
*/
return s;
}
return "";
};
bool __fastcall TPoKeys55::PWM(int x,float y)
{//ustawienie wskazanego PWM (@12Mhz: 12000=1ms=1000Hz)
//iPWM[7]=1024; //1024==85333.3333333333ns=11718.75Hz
iPWM[x]=int(0.5f+0x0FFF*y)&0x0FFF; //0x0FFF=4095
return true;
}
bool __fastcall TPoKeys55::Update(bool pause)
{//funkcja powinna byæ wywo³ywana regularnie, np. raz w ka¿dej ramce ekranowej
if (pause)
{//specjalna procedura, jeœli utracone po³¹czenie spowodowa³o pauzê
iLastCommand=0; //po³¹czenie zosta³o na nowo otwarte
//iFaza=0; //jeden b³¹d i podtrzymanie pauzy jest kontynuowane
}
switch (iFaza)
{case 0: //uaktualnienie PWM raz na jakiœ czas
OutputBuffer[9]=0x3F; //maska u¿ytych PWM
*((int*)(OutputBuffer+10))=iPWM[0]; //PWM1 (pin 22)
*((int*)(OutputBuffer+14))=iPWM[1]; //PWM2 (pin 21)
*((int*)(OutputBuffer+18))=iPWM[2]; //PWM3 (pin 20)
*((int*)(OutputBuffer+22))=iPWM[3]; //PWM4 (pin 19)
*((int*)(OutputBuffer+26))=iPWM[4]; //PWM5 (pin 18)
*((int*)(OutputBuffer+30))=iPWM[5]; //PWM6 (pin 17)
*((int*)(OutputBuffer+34))=iPWM[7]; //PWM period
if (Write(0xCB,1)) //wys³anie ustawieñ (1-ustaw, 0-odczyt)
iRepeats=0; //informacja, ¿e posz³o dobrze
++iFaza; //ta faza zosta³a zakoñczona
//iRepeats=0;
break;
case 1: //odczyt wejϾ analogowych - komenda i przetwarzanie
if (iLastCommand!=0x3A) //asynchroniczne ustawienie kontrolki mo¿e namieszaæ
Write(0x3A,0); //0x3A - Analog inputs reading all analog inputs in one command
else if (Read())
{//jest odebrana ramka i zgodnoœæ numeru ¿¹dania
fAnalog[0]=((InputBuffer[21]<<8)+InputBuffer[22])/4095.0f; //pin 47
fAnalog[1]=((InputBuffer[19]<<8)+InputBuffer[20])/4095.0f; //pin 46
fAnalog[2]=((InputBuffer[17]<<8)+InputBuffer[18])/4095.0f; //pin 45
fAnalog[3]=((InputBuffer[15]<<8)+InputBuffer[16])/4095.0f; //pin 44
fAnalog[4]=((InputBuffer[13]<<8)+InputBuffer[14])/4095.0f; //pin 43
fAnalog[5]=((InputBuffer[11]<<8)+InputBuffer[12])/4095.0f; //pin 42
fAnalog[6]=((InputBuffer[ 9]<<8)+InputBuffer[10])/4095.0f; //pin 41
++iFaza; //skoro odczytano, mo¿na przejœæ do kolejnej fazy
iRepeats=0; //zerowanie licznika prób
}
else ++iRepeats; //licznik nieudanych prób
break;
case 2: //odczyt wejϾ cyfrowych - komenda i przetwarzanie
if (iLastCommand!=0x31) //asynchroniczne ustawienie kontrolki mo¿e namieszaæ
Write(0x31,0); //0x31: blokowy odczyt wejϾ
else if (Read())
{//jest odebrana ramka i zgodnoœæ numeru ¿¹dania
iInputs[0]=*((int*)(InputBuffer+3)); //odczyt 32 bitów
iFaza=3; //skoro odczytano, mo¿na kolejny cykl
iRepeats=0; //zerowanie licznika prób
}
else ++iRepeats; //licznik nieudanych prób
break;
case 3: //ustawienie wyjœæ analogowych, 0..4095 mapowaæ na 0..65520 (<<4)
if (Write(0x41,43-1,(iPWM[6]>>4),(iPWM[6]<<4))) //wys³anie ustawieñ
iRepeats=0; //informacja, ¿e posz³o dobrze
iFaza=0; //++iFaza; //ta faza zosta³a zakoñczona
//powinno jeszcze przyjϾ potwierdzenie o kodzie 0x41
break;
default:
iFaza=0; //na wypadek, gdyby zb³¹dzi³o po jakichœ zmianach w kodzie
//iRepeats=0;
}
if (!iRepeats)
bNoError=true; //jest OK
else if (iRepeats>=10) //youBy 2014-07: przy 5 powtórzeniach sieje mi pauz¹ po 2 razy na sekundê, a przy 10 jest ok
{//przekroczenie liczby prób wymusza kolejn¹ fazê
++iFaza;
iRepeats=1; //w nowej fazie nowe szanse, ale nie od 0!
bNoError=false; //zg³osiæ b³¹d
}
return (bNoError); //true oznacza prawid³owe dzia³anie
//czy w przypadku b³êdu komunikacji z PoKeys w³¹czaæ pauzê?
//dopiero poprawne pod³¹czenie zeruje licznik prób
};

31
Console/PoKeys55.h Normal file
View File

@@ -0,0 +1,31 @@
//---------------------------------------------------------------------------
#ifndef PoKeys55H
#define PoKeys55H
//---------------------------------------------------------------------------
class TPoKeys55
{//komunikacja z PoKeys bez okreœlania przeznaczenia pinów
unsigned char cRequest; //numer ¿¹dania do sprawdzania odpowiedzi
unsigned char OutputBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1
unsigned char InputBuffer[65]; //Allocate a memory buffer equal to our endpoint size + 1
int iPWM[8]; //0-5:wyjœcia PWM,6:analogowe,7:czêstotliwoœc PWM
int iPWMbits;
int iLastCommand;
int iFaza;
int iRepeats; //liczba powtórzeñ
bool bNoError; //zerowany po przepe³nieniu licznika powtórzeñ, ustawiany po udanej operacji
public:
float fAnalog[7]; //wejœcia analogowe, stan <0.0,1.0>
int iInputs[8];
__fastcall TPoKeys55();
__fastcall ~TPoKeys55();
bool __fastcall Connect();
bool __fastcall Close();
bool __fastcall Write(unsigned char c,unsigned char b3,unsigned char b4=0,unsigned char b5=0);
bool __fastcall Read();
bool __fastcall ReadLoop(int i);
AnsiString __fastcall Version();
bool __fastcall PWM(int x,float y);
bool __fastcall Update(bool pause);
};
//---------------------------------------------------------------------------
#endif

141
Curve.cpp Normal file
View File

@@ -0,0 +1,141 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Curve.h"
__fastcall TCurve::TCurve()
{
Values= NULL;
iNumValues= 0;
iNumCols= 0;
}
__fastcall TCurve::~TCurve()
{
for (int i=0; i<iNumValues; i++)
SafeDelete(Values[i]);
SafeDelete(Values);
}
bool __fastcall TCurve::Init(int n, int c)
{
for (int i=0; i<iNumValues; i++)
SafeDelete(Values[i]);
SafeDelete(Values);
iNumValues= n;
iNumCols= c;
Values= new float*[iNumValues];
for (int i=0; i<iNumValues; i++)
Values[i]= new float[iNumCols];
for (int i=0; i<iNumValues; i++)
for (int j=0; j<iNumCols; j++)
Values[i][j]= 0;
}
float __fastcall TCurve::GetValue(int c, float p)
{
int a= floor(p);
int b= ceil(p);
if (a<0)
return Values[0][c];
if (b>=iNumValues)
return Values[iNumValues-1][c];
p-= floor(p);
return Values[a][c]*(1.0f-p)+Values[b][c]*(p);
}
bool __fastcall TCurve::SetValue(int c, float p, float v)
{
int a= floor(p);
int b= ceil(p);
if (a<0)
return false;
if (b>=iNumValues)
return false;
p-= floor(p);
if (p<0.5)
Values[a][c]= v;
else
Values[b][c]= v;
return true;
}
bool __fastcall TCurve::Load(TQueryParserComp *Parser)
{
DecimalSeparator= '.';
AnsiString Token;
int n= Parser->GetNextSymbol().ToInt();
int c= Parser->GetNextSymbol().ToInt();
Init(n,c);
n=0;
int i;
while (!Parser->EOF && n<iNumValues)
{
for (i=0; i<iNumCols; i++)
Values[n][i]= Parser->GetNextSymbol().ToDouble();
n++;
}
DecimalSeparator= ',';
}
bool __fastcall TCurve::LoadFromFile(AnsiString asName)
{
DecimalSeparator= '.';
TFileStream *fs;
fs= new TFileStream(asName, fmOpenRead | fmShareCompat );
AnsiString str= "xxx";
int size= fs->Size;
str.SetLength(size);
fs->Read(str.c_str(),size);
str+= "";
delete fs;
TQueryParserComp *Parser;
Parser= new TQueryParserComp(NULL);
Parser->TextToParse= str;
Parser->First();
Load(Parser);
delete Parser;
DecimalSeparator= ',';
}
#include <stdio.h>
bool __fastcall TCurve::SaveToFile(AnsiString asName)
{
DecimalSeparator= '.';
FILE *stream=NULL;
stream = fopen(asName.c_str(), "w");
AnsiString str;
str= AnsiString(iNumValues);
fprintf(stream, str.c_str());
fprintf(stream, "\n");
for (int i=0; i<iNumValues; i++)
{
str= "";
if (i % 10==0)
str+= "\n";
for (int j=0; j<iNumCols; j++)
str+= FloatToStrF(Values[i][j],ffFixed,6,2)+AnsiString(" ");
str+= AnsiString("\n");
fprintf(stream, str.c_str());
}
fclose(stream);
DecimalSeparator= ',';
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

29
Curve.h Normal file
View File

@@ -0,0 +1,29 @@
//---------------------------------------------------------------------------
#ifndef CurveH
#define CurveH
#include "QueryParserComp.hpp"
#include "Usefull.h"
class TCurve
{
public:
__fastcall TCurve();
__fastcall ~TCurve();
bool __fastcall Init(int n, int c);
float __fastcall GetValue(int c, float p);
bool __fastcall SetValue(int c, float p, float v);
bool __fastcall Load(TQueryParserComp *Parser);
bool __fastcall LoadFromFile(AnsiString asName);
bool __fastcall SaveToFile(AnsiString asName);
int iNumValues;
int iNumCols;
private:
float **Values;
};
//---------------------------------------------------------------------------
#endif

418
Data.h Normal file
View File

@@ -0,0 +1,418 @@
//---------------------------------------------------------------------------
#ifndef DataH
#define DataH
//---------------------------------------------------------------------------
// Modu³ z danymi
//---------------------------------------------------------------------------
struct TDist
{
int x,y;
};
const TDist SectorOrder[]=
{//tabela wspó³rzêdnych sektorów, posortowana wg odleg³oœci
{ 0, 0}, // 0.00
{ 1, 0}, // 1.00
{ 0, 1}, // 1.00
{ 1, 1}, // 1.41
{ 2, 0}, // 2.00
{ 0, 2}, // 2.00
{ 2, 1}, // 2.24
{ 1, 2}, // 2.24
{ 2, 2}, // 2.83 - 9 (566m)
{ 3, 0}, // 3.00
{ 0, 3}, // 3.00
{ 3, 1}, // 3.16
{ 1, 3}, // 3.16
{ 3, 2}, // 3.61
{ 2, 3}, // 3.61
{ 4, 0}, // 4.00 - 16 (800m)
{ 0, 4}, // 4.00
{ 4, 1}, // 4.12
{ 1, 4}, // 4.12
{ 3, 3}, // 4.24 - 20
{ 4, 2}, // 4.47
{ 2, 4}, // 4.47
{ 4, 3}, // 5.00
{ 3, 4}, // 5.00
{ 5, 0}, // 5.00 - 25
{ 0, 5}, // 5.00
{ 5, 1}, // 5.10
{ 1, 5}, // 5.10 - 28
{ 5, 2}, // 5.39
{ 2, 5}, // 5.39
{ 4, 4}, // 5.66
{ 5, 3}, // 5.83
{ 3, 5}, // 5.83
{ 6, 0}, // 6.00
{ 0, 6}, // 6.00
{ 6, 1}, // 6.08 - 36
{ 1, 6}, // 6.08
{ 6, 2}, // 6.32
{ 2, 6}, // 6.32
{ 5, 4}, // 6.40
{ 4, 5}, // 6.40
{ 6, 3}, // 6.71
{ 3, 6}, // 6.71
{ 7, 0}, // 7.00
{ 0, 7}, // 7.00
{ 5, 5}, // 7.07
{ 7, 1}, // 7.07
{ 1, 7}, // 7.07
{ 6, 4}, // 7.21
{ 4, 6}, // 7.21
{ 7, 2}, // 7.28
{ 2, 7}, // 7.28
{ 7, 3}, // 7.62
{ 3, 7}, // 7.62
{ 6, 5}, // 7.81
{ 5, 6}, // 7.81
{ 8, 0}, // 8.00
{ 0, 8}, // 8.00
{ 7, 4}, // 8.06
{ 4, 7}, // 8.06
{ 8, 1}, // 8.06
{ 1, 8}, // 8.06
{ 8, 2}, // 8.25
{ 2, 8}, // 8.25
{ 6, 6}, // 8.49
{ 8, 3}, // 8.54
{ 3, 8}, // 8.54
{ 7, 5}, // 8.60
{ 5, 7}, // 8.60
{ 8, 4}, // 8.94
{ 4, 8}, // 8.94
{ 9, 0}, // 9.00
{ 0, 9}, // 9.00
{ 9, 1}, // 9.06
{ 1, 9}, // 9.06
{ 7, 6}, // 9.22
{ 6, 7}, // 9.22
{ 9, 2}, // 9.22
{ 2, 9}, // 9.22
{ 8, 5}, // 9.43
{ 5, 8}, // 9.43
{ 9, 3}, // 9.49
{ 3, 9}, // 9.49
{ 9, 4}, // 9.85
{ 4, 9}, // 9.85
{ 7, 7}, // 9.90
{ 8, 6}, //10.00
{ 6, 8}, //10.00
{10, 0}, //10.00
{ 0,10}, //10.00
{10, 1}, //10.05
{ 1,10}, //10.05
{10, 2}, //10.20
{ 2,10}, //10.20
{ 9, 5}, //10.30
{ 5, 9}, //10.30
{10, 3}, //10.44
{ 3,10}, //10.44
{ 8, 7}, //10.63
{ 7, 8}, //10.63
{10, 4}, //10.77
{ 4,10}, //10.77
{ 9, 6}, //10.82
{ 6, 9}, //10.82
{11, 0}, //11.00
{ 0,11}, //11.00
{11, 1}, //11.05
{ 1,11}, //11.05
{10, 5}, //11.18
{ 5,10}, //11.18
{11, 2}, //11.18
{ 2,11}, //11.18
{ 8, 8}, //11.31
{ 9, 7}, //11.40
{ 7, 9}, //11.40
{11, 3}, //11.40
{ 3,11}, //11.40
{10, 6}, //11.66
{ 6,10}, //11.66
{11, 4}, //11.70
{ 4,11}, //11.70
{12, 0}, //12.00
{ 0,12}, //12.00
{ 9, 8}, //12.04
{ 8, 9}, //12.04
{12, 1}, //12.04
{ 1,12}, //12.04
{11, 5}, //12.08
{ 5,11}, //12.08
{12, 2}, //12.17
{ 2,12}, //12.17
{10, 7}, //12.21
{ 7,10}, //12.21
{12, 3}, //12.37
{ 3,12}, //12.37
{11, 6}, //12.53
{ 6,11}, //12.53
{12, 4}, //12.65
{ 4,12}, //12.65
{ 9, 9}, //12.73
{10, 8}, //12.81
{ 8,10}, //12.81
{12, 5}, //13.00
{ 5,12}, //13.00
{13, 0}, //13.00
{ 0,13}, //13.00
{11, 7}, //13.04
{ 7,11}, //13.04
{13, 1}, //13.04
{ 1,13}, //13.04
{13, 2}, //13.15
{ 2,13}, //13.15
{13, 3}, //13.34
{ 3,13}, //13.34
{12, 6}, //13.42
{ 6,12}, //13.42
{10, 9}, //13.45
{ 9,10}, //13.45
{11, 8}, //13.60
{ 8,11}, //13.60
{13, 4}, //13.60
{ 4,13}, //13.60
{12, 7}, //13.89
{ 7,12}, //13.89
{13, 5}, //13.93
{ 5,13}, //13.93
{14, 0}, //14.00
{ 0,14}, //14.00
{14, 1}, //14.04
{ 1,14}, //14.04
{10,10}, //14.14
{14, 2}, //14.14
{ 2,14}, //14.14
{11, 9}, //14.21
{ 9,11}, //14.21
{13, 6}, //14.32
{ 6,13}, //14.32
{14, 3}, //14.32
{ 3,14}, //14.32
{12, 8}, //14.42
{ 8,12}, //14.42
{14, 4}, //14.56
{ 4,14}, //14.56
{13, 7}, //14.76
{ 7,13}, //14.76
{11,10}, //14.87
{10,11}, //14.87
{14, 5}, //14.87
{ 5,14}, //14.87
{12, 9}, //15.00
{ 9,12}, //15.00
{15, 0}, //15.00
{ 0,15}, //15.00
{15, 1}, //15.03
{ 1,15}, //15.03
{15, 2}, //15.13
{ 2,15}, //15.13
{14, 6}, //15.23
{ 6,14}, //15.23
{13, 8}, //15.26
{ 8,13}, //15.26
{15, 3}, //15.30
{ 3,15}, //15.30
{15, 4}, //15.52
{ 4,15}, //15.52
{11,11}, //15.56
{12,10}, //15.62
{10,12}, //15.62
{14, 7}, //15.65
{ 7,14}, //15.65
{13, 9}, //15.81
{ 9,13}, //15.81
{15, 5}, //15.81
{ 5,15}, //15.81
{16, 0}, //16.00
{ 0,16}, //16.00
{16, 1}, //16.03
{ 1,16}, //16.03
{14, 8}, //16.12
{ 8,14}, //16.12
{16, 2}, //16.12
{ 2,16}, //16.12
{15, 6}, //16.16
{ 6,15}, //16.16
{12,11}, //16.28
{11,12}, //16.28
{16, 3}, //16.28
{ 3,16}, //16.28
{13,10}, //16.40
{10,13}, //16.40
{16, 4}, //16.49
{ 4,16}, //16.49
{15, 7}, //16.55
{ 7,15}, //16.55
{14, 9}, //16.64
{ 9,14}, //16.64
{16, 5}, //16.76
{ 5,16}, //16.76
{12,12}, //16.97
{15, 8}, //17.00
{ 8,15}, //17.00
{17, 0}, //17.00
{ 0,17}, //17.00
{13,11}, //17.03
{11,13}, //17.03
{17, 1}, //17.03
{ 1,17}, //17.03
{16, 6}, //17.09
{ 6,16}, //17.09
{17, 2}, //17.12
{ 2,17}, //17.12
{14,10}, //17.20
{10,14}, //17.20
{17, 3}, //17.26
{ 3,17}, //17.26
{16, 7}, //17.46
{ 7,16}, //17.46
{17, 4}, //17.46
{ 4,17}, //17.46
{15, 9}, //17.49
{ 9,15}, //17.49
{13,12}, //17.69
{12,13}, //17.69
{17, 5}, //17.72
{ 5,17}, //17.72
{14,11}, //17.80
{11,14}, //17.80
{16, 8}, //17.89
{ 8,16}, //17.89
{18, 0}, //18.00
{ 0,18}, //18.00
{15,10}, //18.03
{10,15}, //18.03
{17, 6}, //18.03
{ 6,17}, //18.03
{18, 1}, //18.03
{ 1,18}, //18.03
{18, 2}, //18.11
{ 2,18}, //18.11
{18, 3}, //18.25
{ 3,18}, //18.25
{16, 9}, //18.36
{ 9,16}, //18.36
{13,13}, //18.38
{17, 7}, //18.38
{ 7,17}, //18.38
{14,12}, //18.44
{12,14}, //18.44
{18, 4}, //18.44
{ 4,18}, //18.44
{15,11}, //18.60
{11,15}, //18.60
{18, 5}, //18.68
{ 5,18}, //18.68
{17, 8}, //18.79
{ 8,17}, //18.79
{16,10}, //18.87
{10,16}, //18.87
{18, 6}, //18.97
{ 6,18}, //18.97
{19, 0}, //19.00
{ 0,19}, //19.00
{19, 1}, //19.03
{ 1,19}, //19.03
{14,13}, //19.10
{13,14}, //19.10
{19, 2}, //19.10
{ 2,19}, //19.10
{15,12}, //19.21
{12,15}, //19.21
{17, 9}, //19.24
{ 9,17}, //19.24
{19, 3}, //19.24
{ 3,19}, //19.24
{18, 7}, //19.31
{ 7,18}, //19.31
{16,11}, //19.42
{11,16}, //19.42
{19, 4}, //19.42
{ 4,19}, //19.42
{19, 5}, //19.65
{ 5,19}, //19.65
{18, 8}, //19.70
{ 8,18}, //19.70
{17,10}, //19.72
{10,17}, //19.72
{14,14}, //19.80
{15,13}, //19.85
{13,15}, //19.85
{19, 6}, //19.92
{ 6,19}, //19.92
{16,12}, //20.00
{12,16}, //20.00
{18, 9}, //20.12
{ 9,18}, //20.12
{17,11}, //20.25
{11,17}, //20.25
{19, 7}, //20.25
{ 7,19}, //20.25
{15,14}, //20.52
{14,15}, //20.52
{18,10}, //20.59
{10,18}, //20.59
{16,13}, //20.62
{13,16}, //20.62
{19, 8}, //20.62
{ 8,19}, //20.62
{17,12}, //20.81
{12,17}, //20.81
{19, 9}, //21.02
{ 9,19}, //21.02
{18,11}, //21.10
{11,18}, //21.10
{15,15}, //21.21
{16,14}, //21.26
{14,16}, //21.26
{17,13}, //21.40
{13,17}, //21.40
{19,10}, //21.47
{10,19}, //21.47
{18,12}, //21.63
{12,18}, //21.63
{16,15}, //21.93
{15,16}, //21.93
{19,11}, //21.95
{11,19}, //21.95
{17,14}, //22.02
{14,17}, //22.02
{18,13}, //22.20
{13,18}, //22.20
{19,12}, //22.47
{12,19}, //22.47
{16,16}, //22.63
{17,15}, //22.67
{15,17}, //22.67
{18,14}, //22.80
{14,18}, //22.80
{19,13}, //23.02
{13,19}, //23.02
{17,16}, //23.35
{16,17}, //23.35
{18,15}, //23.43
{15,18}, //23.43
{19,14}, //23.60
{14,19}, //23.60
{17,17}, //24.04
{18,16}, //24.08
{16,18}, //24.08
{19,15}, //24.21
{15,19}, //24.21
{18,17}, //24.76
{17,18}, //24.76
{19,16}, //24.84
{16,19}, //24.84
{18,18}, //25.46
{19,17}, //25.50
{17,19}, //25.50
{19,18}, //26.17
{18,19}, //26.17
{19,19} //26.87 - 400 (5374m)
};
#endif

BIN
DirectX/DSOUND.LIB Normal file

Binary file not shown.

4210
Driver.cpp Normal file

File diff suppressed because it is too large Load Diff

320
Driver.h Normal file
View File

@@ -0,0 +1,320 @@
//---------------------------------------------------------------------------
#ifndef DriverH
#define DriverH
#include "Classes.h"
#include "dumb3d.h"
#include <fstream>
using namespace Math3D;
enum TOrders
{//rozkazy dla AI
Wait_for_orders=0, //czekanie na dostarczenie następnych rozkazów
//operacje tymczasowe
Prepare_engine=1, //włączenie silnika
Release_engine=2, //wyłączenie silnika
Change_direction=4, //zmiana kierunku (bez skanowania sygnalizacji)
Connect=8, //podłączanie wagonów (z częściowym skanowaniem sygnalizacji)
Disconnect=0x10, //odłączanie wagonów (bez skanowania sygnalizacji)
//jazda
Shunt=0x20, //tryb manewrowy
Obey_train=0x40, //tryb pociągowy
Jump_to_first_order=0x60 //zapęlenie do pierwszej pozycji (po co?)
};
enum TMovementStatus
{//flagi bitowe ruchu (iDrivigFlags)
moveStopCloser=1, //podjechać blisko W4 (nie podjeżdżać na początku ani po zmianie czoła)
moveStopPoint=2, //stawać na W4 (wyłączone podczas zmiany czoła)
moveActive=4, //pojazd jest załączony i skanuje
movePress=8, //dociskanie przy odłączeniu (zamiast zmiennej Prepare2press)
moveConnect=0x10, //jest blisko innego pojazdu i można próbować podłączyć
movePrimary=0x20, //ma priorytet w składzie (master)
moveLate=0x40, //flaga spóźnienia, włączy bardziej
moveStopHere=0x80, //nie podjeżdżać do semafora, jeśli droga nie jest wolna
moveStartHorn=0x100, //podawaj sygnał po podaniu wolnej drogi
moveStartHornNow=0x200, //podaj sygnał po odhamowaniu
moveStartHornDone=0x400, //podano sygnał po podaniu wolnej drogi
moveOerlikons=0x800, //skład wyłącznie z zaworami? Oerlikona
moveIncSpeed=0x1000, //załączenie jazdy (np. dla EZT)
moveTrackEnd=0x2000, //dalsza jazda do przodu trwale ograniczona (W5, koniec toru)
moveSwitchFound=0x4000, //na drodze skanowania do przodu jest rozjazd
moveGuardSignal=0x8000, //sygnał od kierownika (minął czas postoju)
moveVisibility=0x10000, //jazda na widoczność po przejechaniu S1 na SBL
moveDoorOpened=0x20000, //drzwi zostały otwarte - doliczyć czas na zamknięcie
movePushPull=0x40000 //zmiana czoła przez zmianę kabiny - nie odczepiać przy zmianie kierunku
};
enum TStopReason
{//powód zatrzymania, dodawany do SetVelocity 0 - w zasadzie do usunięcia
stopNone, //nie ma powodu - powinien jechać
stopSleep, //nie został odpalony, to nie pojedzie
stopSem, //semafor zamknięty
stopTime, //czekanie na godzinę odjazdu
stopEnd, //brak dalszej części toru
stopDir, //trzeba stanąć, by zmienić kierunek jazdy
stopJoin, //stoi w celu połączenia wagonów
stopBlock, //przeszkoda na drodze ruchu
stopComm, //otrzymano taką komendę (niewiadomego pochodzenia)
stopOut, //komenda wyjazdu poza stację (raczej nie powinna zatrzymywać!)
stopRadio, //komunikat przekazany radiem (Radiostop)
stopExt, //komenda z zewnątrz
stopError //z powodu błędu w obliczeniu drogi hamowania
};
enum TAction
{//przechowanie aktualnego stanu AI od poprzedniego przebłysku świadomości
actUnknown, //stan nieznany (domyślny na początku)
actPantUp, //podnieś pantograf (info dla użytkownika)
actConv, //załącz przetwornicę (info dla użytkownika)
actCompr, //załącz sprężarkę (info dla użytkownika)
actSleep, //śpi (wygaszony)
actDrive, //jazda
actGo, //ruszanie z miejsca
actSlow, //przyhamowanie przed ograniczeniem
sctStop, //hamowanie w celu precyzyjnego zatrzymania
actIdle, //luzowanie składu przed odjazdem
actRelease, //luzowanie składu po zmniejszeniu prędkości
actConnect, //dojazd w celu podczepienia
actWait, //czekanie na przystanku
actReady, //zgłoszona gotowość do odjazdu od kierownika
actEmergency, //hamowanie awaryjne
actGoUphill, //ruszanie pod górę
actTest, //hamowanie kontrolne (podczas jazdy)
actTrial //próba hamulca (na postoju)
};
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 fAcc;
int iFlags;
//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
//0x10000=zatkanie
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
};
void __fastcall CommandCheck();
public:
void __fastcall Clear();
bool __fastcall Update(vector3 *p,vector3 *dir,double &len);
bool __fastcall Set(TEvent *e,double d);
void __fastcall Set(TTrack *t,double d,int f);
AnsiString __fastcall TableText();
};
//----------------------------------------------------------------------------
static const bool Aggressive=true;
static const bool Easyman=false;
static const bool AIdriver=true;
static const bool Humandriver=false;
static const int maxorders=32; //ilość rozkazów w tabelce
static const int maxdriverfails=4; //ile błędów może zrobić AI zanim zmieni nastawienie
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; //najbliższe zmiany prędkości
int iSpeedTableSize; //wielkość tabelki
int iFirst; //aktualna pozycja w tabeli (modulo iSpeedTableSize)
int iLast; //ostatnia wypełniona pozycja w tabeli <iFirst (modulo iSpeedTableSize)
int iTableDirection; //kierunek zapełnienia tabelki względem pojazdu z AI
double fLastVel; //prędkość na poprzednio sprawdzonym torze
TTrack *tLast; //ostatni analizowany tor
TEvent *eSignSkip; //można pominąć ten SBL po zatrzymaniu
private: //parametry aktualnego składu
double fLength; //długość składu (do wyciągania z ograniczeń)
double fMass; //całkowita masa do liczenia stycznej składowej grawitacji
double fAccGravity; //przyspieszenie składowej stycznej grawitacji
public:
TEvent *eSignNext; //sygnał zmieniający prędkość, do pokazania na [F2]
AnsiString asNextStop; //nazwa następnego punktu zatrzymania wg rozkładu
int iStationStart; //numer pierwszej stacji pokazywanej na podglądzie rozkładu
private: //parametry sterowania pojazdem (stan, hamowanie)
double fShuntVelocity; //maksymalna prędkość manewrowania, zależy m.in. od składu
int iVehicles; //ilość pojazdów w składzie
int iEngineActive; //ABu: Czy silnik byl juz zalaczony; Ra: postęp w załączaniu
//vector3 vMechLoc; //pozycja pojazdu do liczenia odległości od semafora (?)
bool Psyche;
int iDrivigFlags; //flagi bitowe ruchu
double fDriverBraking; //po pomnożeniu przez v^2 [km/h] daje ~drogę hamowania [m]
double fDriverDist; //dopuszczalna odległość podjechania do przeszkody
double fVelMax; //maksymalna prędkość składu (sprawdzany każdy pojazd)
double fBrakeDist; //przybliżona droga hamowania
double fAccThreshold; //próg opóźnienia dla zadziałania hamulca
public:
double fLastStopExpDist; //odległość wygasania ostateniego przystanku
double ReactionTime; //czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime; //wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
private:
double fReady; //poziom odhamowania wagonów
bool Ready; //ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow
double LastUpdatedTime; //czas od ostatniego logu
double ElapsedTime; //czas od poczatku logu
double deltalog; //przyrost czasu
double LastReactionTime;
double fActionTime; //czas używany przy regulacji prędkości i zamykaniu drzwi
TAction eAction; //aktualny stan
bool HelpMeFlag; //wystawiane True jesli cos niedobrego sie dzieje
public:
bool AIControllFlag; //rzeczywisty/wirtualny maszynista
int iRouteWanted; //oczekiwany kierunek jazdy (0-stop,1-lewo,2-prawo,3-prosto) np. odpala migacz lub czeka na stan zwrotnicy
private:
TDynamicObject *pVehicle; //pojazd w którym siedzi sterujący
TDynamicObject *pVehicles[2]; //skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
TMoverParameters *mvControlling; //jakim pojazdem steruje (może silnikowym w EZT)
TMoverParameters *mvOccupied; //jakim pojazdem hamuje
Mtable::TTrainParameters *TrainParams; //rozkład jazdy zawsze jest, nawet jeśli pusty
//int TrainNumber; //numer rozkladowy tego pociagu
//AnsiString OrderCommand; //komenda pobierana z pojazdu
//double OrderValue; //argument komendy
int iRadioChannel; //numer aktualnego kanału radiowego
TTextSound *tsGuardSignal; //komunikat od kierownika
int iGuardRadio; //numer kanału radiowego kierownika (0, gdy nie używa radia)
public:
double AccPreferred; //preferowane przyspieszenie (wg psychiki kierującego, zmniejszana przy wykryciu kolizji)
double AccDesired; //przyspieszenie, jakie ma utrzymywać (<0:nie przyspieszaj,<-0.1:hamuj)
double VelDesired; //predkość, z jaką ma jechać, wynikająca z analizy tableki; <=VelSignal
double fAccDesiredAv; //uśrednione przyspieszenie z kolejnych przebłysków świadomości, żeby ograniczyć migotanie
private:
double VelforDriver; //prędkość, używana przy zmianie kierunku (ograniczenie przy nieznajmości szlaku?)
double VelSignal; //predkość zadawana przez semafor (funkcją SetVelocity())
double VelLimit; //predkość zadawana przez event jednokierunkowego ograniczenia prędkości (PutValues albo komendą)
public:
double VelNext; //prędkość, jaka ma być po przejechaniu długości ProximityDist
private:
//double fProximityDist; //odleglosc podawana w SetProximityVelocity(); >0:przeliczać do punktu, <0:podana wartość
public:
double ActualProximityDist; //odległość brana pod uwagę przy wyliczaniu prędkości i przyspieszenia
private:
vector3 vCommandLocation; //polozenie wskaznika, sygnalizatora lub innego obiektu do ktorego odnosi sie komenda
TOrders OrderList[maxorders]; //lista rozkazów
int OrderPos,OrderTop; //rozkaz aktualny oraz wolne miejsce do wstawiania nowych
std::ofstream LogFile; //zapis parametrow fizycznych
std::ofstream AILogFile; //log AI
bool MaxVelFlag;
bool MinVelFlag;
int iDirection; //kierunek jazdy względem sprzęgów pojazdu, w którym siedzi AI (1=przód,-1=tył)
int iDirectionOrder; //żadany kierunek jazdy (służy do zmiany kierunku)
int iVehicleCount; //ilość pojazdów do odłączenia albo zabrania ze składu (-1=wszystkie)
int iCoupler; //maska sprzęgu, jaką należy użyć przy łączeniu (po osiągnięciu trybu Connect), 0 gdy jazda bez łączenia
int iDriverFailCount; //licznik błędów AI
bool Need_TryAgain; //true, jeśli druga pozycja w elektryku nie załapała
bool Need_BrakeRelease;
public:
double fMinProximityDist; //minimalna oległość do przeszkody, jaką należy zachować
double fOverhead1; //informacja o napięciu w sieci trakcyjnej (0=brak drutu, zatrzymaj!)
double fOverhead2; //informacja o sposobie jazdy (-1=normalnie, 0=bez prądu, >0=z opuszczonym i ograniczeniem prędkości)
int iOverheadZero; //suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami
int iOverheadDown; //suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami
double fVoltage; //uśrednione napięcie sieci: przy spadku poniżej wartości minimalnej opóźnić rozruch o losowy czas
private:
double fMaxProximityDist; //akceptowalna odległość stanięcia przed przeszkodą
TStopReason eStopReason; //powód zatrzymania przy ustawieniu zerowej prędkości
AnsiString VehicleName;
double fVelPlus; //dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
double fVelMinus; //margines obniżenia prędkości, powodujący załączenie napędu
double fWarningDuration; //ile czasu jeszcze trąbić
double fStopTime; //czas postoju przed dalszą jazdą (np. na przystanku)
double WaitingTime; //zliczany czas oczekiwania do samoistnego ruszenia
double WaitingExpireTime; //maksymlany czas oczekiwania do samoistnego ruszenia
//TEvent* eSignLast; //ostatnio znaleziony sygnał, o ile nie minięty
private: //---//---//---//---// koniec zmiennych, poniżej metody //---//---//---//---//
void __fastcall SetDriverPsyche();
bool __fastcall PrepareEngine();
bool __fastcall ReleaseEngine();
bool __fastcall IncBrake();
bool __fastcall DecBrake();
bool __fastcall IncSpeed();
bool __fastcall DecSpeed(bool force=false);
void __fastcall SpeedSet();
void __fastcall Doors(bool what);
void __fastcall RecognizeCommand(); //odczytuje komende przekazana lokomotywie
void __fastcall Activation(); //umieszczenie obsady w odpowiednim członie
void __fastcall ControllingSet(); //znajduje człon do sterowania
void __fastcall AutoRewident(); //ustawia hamulce w składzie
public:
Mtable::TTrainParameters* __fastcall Timetable() {return TrainParams;};
void __fastcall PutCommand(AnsiString NewCommand,double NewValue1,double NewValue2,const _mover::TLocation &NewLocation,TStopReason reason=stopComm);
bool __fastcall PutCommand(AnsiString NewCommand,double NewValue1,double NewValue2,const vector3 *NewLocation,TStopReason reason=stopComm);
bool __fastcall UpdateSituation(double dt); //uruchamiac przynajmniej raz na sekundę
//procedury dotyczace rozkazow dla maszynisty
void __fastcall SetVelocity(double NewVel,double NewVelNext,TStopReason r=stopNone); //uaktualnia informacje o prędkości
bool __fastcall SetProximityVelocity(double NewDist,double NewVelNext); //uaktualnia informacje o prędkości przy nastepnym semaforze
public:
void __fastcall JumpToNextOrder();
void __fastcall JumpToFirstOrder();
void __fastcall OrderPush(TOrders NewOrder);
void __fastcall OrderNext(TOrders NewOrder);
TOrders __fastcall OrderCurrentGet();
TOrders __fastcall OrderNextGet();
bool __fastcall CheckVehicles(TOrders user=Wait_for_orders);
private:
void __fastcall CloseLog();
void __fastcall OrderCheck();
public:
void __fastcall OrdersInit(double fVel);
void __fastcall OrdersClear();
void __fastcall OrdersDump();
__fastcall TController
(bool AI,
TDynamicObject *NewControll,
bool InitPsyche,
bool primary=true //czy ma aktywnie prowadzić?
);
AnsiString __fastcall OrderCurrent();
void __fastcall WaitingSet(double Seconds);
private:
AnsiString __fastcall Order2Str(TOrders Order);
void __fastcall DirectionForward(bool forward);
int __fastcall OrderDirectionChange(int newdir,TMoverParameters *Vehicle);
void __fastcall Lights(int head,int rear);
double __fastcall Distance(vector3 &p1,vector3 &n,vector3 &p2);
private: //Ra: metody obsługujące skanowanie toru
TEvent* __fastcall CheckTrackEvent(double fDirection,TTrack *Track);
bool __fastcall TableCheckEvent(TEvent *e);
bool __fastcall TableAddNew();
bool __fastcall TableNotFound(TEvent *e);
void __fastcall TableClear();
TEvent* __fastcall TableCheckTrackEvent(double fDirection,TTrack *Track);
void __fastcall TableTraceRoute(double fDistance,TDynamicObject *pVehicle=NULL);
void __fastcall TableCheck(double fDistance);
TCommandType __fastcall TableUpdate(double &fVelDes,double &fDist,double &fNext,double &fAcc);
void __fastcall TablePurger();
private: //Ra: stare funkcje skanujące, używane do szukania sygnalizatora z tyłu
bool __fastcall BackwardTrackBusy(TTrack *Track);
TEvent* __fastcall CheckTrackEventBackward(double fDirection,TTrack *Track);
TTrack* __fastcall BackwardTraceRoute(double &fDistance,double &fDirection,TTrack *Track,TEvent*&Event);
void __fastcall SetProximityVelocity(double dist,double vel,const vector3 *pos);
TCommandType __fastcall BackwardScan();
public:
void __fastcall PhysicsLog();
AnsiString __fastcall StopReasonText();
__fastcall ~TController();
AnsiString __fastcall NextStop();
void __fastcall TakeControl(bool yes);
AnsiString __fastcall Relation();
AnsiString __fastcall TrainName();
int __fastcall StationCount();
int __fastcall StationIndex();
bool __fastcall IsStop();
bool __fastcall Primary() {return this?bool(iDrivigFlags&movePrimary):false;};
int inline __fastcall DrivigFlags() {return iDrivigFlags;};
void __fastcall MoveTo(TDynamicObject *to);
void __fastcall DirectionInitial();
AnsiString __fastcall TableText(int i);
int __fastcall CrossRoute(TTrack *tr);
void __fastcall RouteSwitch(int d);
AnsiString __fastcall OwnerName();
};
#endif

4358
DynObj.cpp Normal file

File diff suppressed because it is too large Load Diff

440
DynObj.h Normal file
View File

@@ -0,0 +1,440 @@
//---------------------------------------------------------------------------
#ifndef DynObjH
#define DynObjH
#include "Classes.h"
#include "TrkFoll.h"
#include "QueryParserComp.hpp"
#include "Mover.h"
#include "TractionPower.h"
//McZapkie:
#include "MdlMngr.h"
#include "RealSound.h"
#include "AdvSound.h"
#include "Button.h"
#include "AirCoupler.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
const ANIM_TYPES=7; //Ra: ilość typów animacji
const ANIM_WHEELS =0; //koła
const ANIM_DOORS =1; //drzwi
const ANIM_LEVERS =2; //elementy obracane (wycieraczki, koła skrętne, przestawiacze, klocki ham.)
const ANIM_BUFFERS=3; //elementy przesuwane (zderzaki)
const ANIM_BOOGIES=4; //wózki (są skręcane w dwóch osiach)
const ANIM_PANTS =5; //pantografy
const ANIM_STEAMS =6; //napęd parowozu
class TAnim;
typedef void (__closure *TUpdate)(TAnim *pAnim); //typ funkcji aktualizującej położenie submodeli
//McZapkie-250202
const MaxAxles=16; //ABu 280105: zmienione z 8 na 16
//const MaxAnimatedAxles=16; //i to tez.
//const MaxAnimatedDoors=16; //NBMX wrzesien 2003
/*
Ra: Utworzyć klasę wyposażenia opcjonalnego, z której będą dziedziczyć klasy drzwi,
pantografów, napędu parowozu i innych ruchomych części pojazdów. Klasy powinny być
pseudo-wirtualne, bo wirtualne mogą obniżać wydajnosść.
Przy wczytywaniu MMD utworzyć tabelę wskaźnikow na te dodatki. Przy wyświetlaniu
pojazdu wykonywać Update() na kolejnych obiektach wyposażenia.
Rozważyć użycie oddzielnych modeli dla niektórych pojazdów (np. lokomotywy), co
zaoszczędziło by czas ustawiania animacji na modelu wspólnym dla kilku pojazdów,
szczególnie dla pojazdów w danej chwili nieruchomych (przy dużym zagęszczeniu
modeli na stacjach na ogół przewaga jest tych nieruchomych).
*/
class TAnimValveGear
{//współczynniki do animacji parowozu (wartości przykładowe dla Pt47)
int iValues; //ilość liczb (wersja):
float fKorbowodR; //długość korby (pół skoku tłoka) [m]: 0.35
float fKorbowodL; //długość korbowodu [m]: 3.8
float fDrazekR; //promień mimośrodu (drążka) [m]: 0.18
float fDrazekL; //dł. drążka mimośrodowego [m]: 2.55889
float fJarzmoV; //wysokość w pionie osi jarzma od osi koła [m]: 0.751
float fJarzmoH; //odległość w poziomie osi jarzma od osi koła [m]: 2.550
float fJarzmoR; //promień jarzma do styku z drążkiem [m]: 0.450
float fJarzmoA; //kąt mimośrodu względem kąta koła [°]: -96.77416667
float fWdzidloL; //długość wodzidła [m]: 2.0
float fWahaczH; //długość wahacza (góra) [m]: 0.14
float fSuwakH; //wysokość osi suwaka ponad osią koła [m]: 0.62
float fWahaczL; //długość wahacza (dół) [m]: 0.84
float fLacznikL; //długość łącznika wahacza [m]: 0.75072
float fRamieL; //odległość ramienia krzyżulca od osi koła [m]: 0.192
float fSuwakL; //odległość środka tłoka/suwaka od osi koła [m]: 5.650
//dołożyć parametry drążka nastawnicy
//albo nawet zrobić dynamiczną tablicę float[] i w nią pakować wszelkie współczynniki, potem używać indeksów
//współczynniki mogą być wspólne dla 2-4 tłoków, albo każdy tłok może mieć odrębne
};
class TAnimPant
{//współczynniki do animacji pantografu
public:
vector3 vPos; //Ra: współrzędne punktu zerowego pantografu (X dodatnie dla przedniego)
double fLenL1; //długość dolnego ramienia 1, odczytana z modelu
double fLenU1; //długość górnego ramienia 1, odczytana z modelu
double fLenL2; //długość dolnego ramienia 2, odczytana z modelu
double fLenU2; //długość górnego ramienia 2, odczytana z modelu
double fHoriz; //przesunięcie ślizgu w długości pojazdu względem osi obrotu dolnego ramienia
double fHeight; //wysokość ślizgu ponad oś obrotu, odejmowana od wysokości drutu
double fWidth; //połowa szerokości roboczej ślizgu, do wykrycia ześlizgnięcia się drutu
double fAngleL0; //Ra: początkowy kąt dolnego ramienia (odejmowany przy animacji)
double fAngleU0; //Ra: początkowy kąt górnego ramienia (odejmowany przy animacji)
double PantTraction; //Winger 170204: wysokość drutu ponad punktem na wysokości vPos.y p.g.s.
double PantWys; //Ra: aktualna wysokość uniesienia ślizgu do porównania z wysokością drutu
double fAngleL; //Winger 160204: aktualny kąt ramienia dolnego
double fAngleU; //Ra: aktualny kąt ramienia górnego
double NoVoltTime; //czas od utraty kontaktu z drutem
TTraction *hvPowerWire; //aktualnie podczepione druty, na razie tu
float fWidthExtra; //dodatkowy rozmiar poziomy poza część roboczą (fWidth)
float fHeightExtra[5]; //łamana symulująca kształt nabieżnika
//double fHorizontal; //Ra 2015-01: położenie drutu względem osi pantografu
void __fastcall AKP_4E();
};
class TAnim
{//klasa animowanej części pojazdu (koła, drzwi, pantografy, burty, napęd parowozu, siłowniki itd.)
public:
union
{
TSubModel *smAnimated; //animowany submodel (jeśli tylko jeden, np. oś)
TSubModel **smElement; //jeśli animowanych elementów jest więcej (pantograf, napęd parowozu)
int iShift; //przesunięcie przed przydzieleniem wskaźnika
};
union
{//parametry animacji
TAnimValveGear *pValveGear; //współczynniki do animacji parowozu
double *dWheelAngle; //wskaźnik na kąt obrotu osi
float *fParam; //różne parametry dla animacji
TAnimPant *fParamPants; //różne parametry dla animacji
};
union
{//wskaźnik na obiekt odniesienia
double *fDoubleBase; //jakiś double w fizyce
float *fFloatBase; //jakiś float w fizyce
int *iIntBase; //jakiś int w fizyce
};
//void _fastcall Update(); //wskaźnik do funkcji aktualizacji animacji
int iFlags; //flagi animacji
float fMaxDist; //do jakiej odległości wykonywana jest animacja
float fSpeed; //parametr szybkości animacji
int iNumber; //numer kolejny obiektu
public:
__fastcall TAnim();
__fastcall ~TAnim();
TUpdate yUpdate; //metoda TDynamicObject aktualizująca animację
int __fastcall TypeSet(int i,int fl=0); //ustawienie typu
void __fastcall Parovoz(); //wykonanie obliczeń animacji
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class TDynamicObject
{//klasa pojazdu
private: //położenie pojazdu w świecie oraz parametry ruchu
vector3 vPosition; //Ra: pozycja pojazdu liczona zaraz po przesunięciu
vector3 vCoulpler[2]; //współrzędne sprzęgów do liczenia zderzeń czołowych
vector3 vUp,vFront,vLeft; //wektory jednostkowe ustawienia pojazdu
int iDirection; //kierunek pojazdu względem czoła składu (1=zgodny,0=przeciwny)
TTrackShape ts; //parametry toru przekazywane do fizyki
TTrackParam tp; //parametry toru przekazywane do fizyki
TTrackFollower Axle0; //oś z przodu (od sprzęgu 0)
TTrackFollower Axle1; //oś z tyłu (od sprzęgu 1)
int iAxleFirst; //numer pierwszej osi w kierunku ruchu (oś wiążąca pojazd z torem i wyzwalająca eventy)
float fAxleDist; //rozstaw wózków albo osi do liczenia proporcji zacienienia
vector3 modelRot; //obrot pudła względem świata - do przeanalizowania, czy potrzebne!!!
//bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów
TDynamicObject* __fastcall ABuFindNearestObject(TTrack *Track,TDynamicObject *MyPointer,int &CouplNr);
public: //parametry położenia pojazdu dostępne publicznie
AnsiString asTrack; //nazwa toru początkowego; wywalić?
AnsiString asDestination; //dokąd pojazd ma być kierowany "(stacja):(tor)"
matrix4x4 mMatrix; //macierz przekształcenia do renderowania modeli
TMoverParameters *MoverParameters; //parametry fizyki ruchu oraz przeliczanie
//TMoverParameters *pControlled; //wskaźnik do sterowanego członu silnikowego
TDynamicObject *NextConnected; //pojazd podłączony od strony sprzęgu 1 (kabina -1)
TDynamicObject *PrevConnected; //pojazd podłączony od strony sprzęgu 0 (kabina 1)
int NextConnectedNo; //numer sprzęgu podłączonego z tyłu
int PrevConnectedNo; //numer sprzęgu podłączonego z przodu
double fScanDist; //odległość skanowania torów na obecność innych pojazdów
public: //modele składowe pojazdu
TModel3d *mdModel; //model pudła
TModel3d *mdLoad; //model zmiennego ładunku
TModel3d *mdPrzedsionek; //model przedsionków dla EZT - może użyć mdLoad zamiast?
TModel3d *mdKabina; //model kabiny dla użytkownika; McZapkie-030303: to z train.h
TModel3d *mdLowPolyInt; //ABu 010305: wnetrze lowpoly
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
public: //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:
int iAnimations; //liczba obiektów animujących
TAnim *pAnimations; //obiekty animujące (zawierają wskaźnik do funkcji wykonującej animację)
TSubModel **pAnimated; //lista animowanych submodeli (może być ich więcej niż obiektów animujących)
double dWheelAngle[3]; //kąty obrotu kół: 0=przednie toczne, 1=napędzające i wiązary, 2=tylne toczne
void UpdateNone(TAnim *pAnim) {}; //animacja pusta (funkcje ustawiania submodeli, gdy blisko kamery)
void UpdateAxle(TAnim *pAnim); //animacja osi
void UpdateBoogie(TAnim *pAnim); //animacja wózka
void UpdateDoorTranslate(TAnim *pAnim); //animacja drzwi - przesuw
void UpdateDoorRotate(TAnim *pAnim); //animacja drzwi - obrót
void UpdateDoorFold(TAnim *pAnim); //animacja drzwi - składanie
void UpdatePant(TAnim *pAnim); //animacja pantografu
void UpdateLeverDouble(TAnim *pAnim); //animacja gałki zależna od double
void UpdateLeverFloat(TAnim *pAnim); //animacja gałki zależna od float
void UpdateLeverInt(TAnim *pAnim); //animacja gałki zależna od int (wartość)
void UpdateLeverEnum(TAnim *pAnim); //animacja gałki zależna od int (lista kątów)
private: //Ra: ciąg dalszy animacji, dopiero do ogarnięcia
//ABuWozki 060504
vector3 bogieRot[2]; //Obroty wozkow w/m korpusu
TSubModel *smBogie[2]; //Wyszukiwanie max 2 wozkow
TSubModel *smWahacze[4]; //wahacze (np. nogi, dźwignia w drezynie)
TSubModel *smBrakeMode; //Ra 15-01: nastawa hamulca też
TSubModel *smLoadMode; //Ra 15-01: nastawa próżny/ładowny
double fWahaczeAmp;
//Winger 160204 - pantografy
double pantspeedfactor;
//animacje typu przesuw
TSubModel *smBuforLewy[2];
TSubModel *smBuforPrawy[2];
TAnimValveGear *pValveGear;
vector3 vFloor; //podłoga dla ładunku
public:
TAnim *pants; //indeks obiektu animującego dla pantografu 0
double NoVoltTime; //czas od utraty zasilania
double dDoorMoveL; //NBMX
double dDoorMoveR; //NBMX
TSubModel *smBrakeSet; //nastawa hamulca (wajcha)
TSubModel *smLoadSet; //nastawa ładunku (wajcha)
TSubModel *smWiper; //wycieraczka (poniekąd też wajcha)
//Ra: koneic animacji do ogarnięcia
private:
void ABuLittleUpdate(double ObjSqrDist);
bool btnOn; //ABu: czy byly uzywane buttony, jesli tak, to po renderingu wylacz
//bo ten sam model moze byc jeszcze wykorzystany przez inny obiekt!
double __fastcall ComputeRadius(vector3 p1,vector3 p2,vector3 p3,vector3 p4);
TButton btCoupler1; //sprzegi
TButton btCoupler2;
TAirCoupler btCPneumatic1; //sprzegi powietrzne //yB - zmienione z Button na AirCoupler - krzyzyki
TAirCoupler btCPneumatic2;
TAirCoupler btCPneumatic1r; //ABu: to zeby nie bylo problemow przy laczeniu wagonow,
TAirCoupler btCPneumatic2r; // jesli beda polaczone sprzegami 1<->1 lub 0<->0
TAirCoupler btPneumatic1; //ABu: sprzegi powietrzne zolte
TAirCoupler btPneumatic2;
TAirCoupler btPneumatic1r; //ABu: analogicznie jak 4 linijki wyzej
TAirCoupler btPneumatic2r;
TButton btCCtrl1; //sprzegi sterowania
TButton btCCtrl2;
TButton btCPass1; //mostki przejsciowe
TButton btCPass2;
char cp1, sp1, cp2, sp2; //ustawienia węży
TButton btEndSignals11; //sygnalu konca pociagu
TButton btEndSignals13;
TButton btEndSignals21;
TButton btEndSignals23;
TButton btEndSignals1; //zeby bylo kompatybilne ze starymi modelami...
TButton btEndSignals2;
TButton btEndSignalsTab1; //sygnaly konca pociagu (blachy)
TButton btEndSignalsTab2;
TButton btHeadSignals11; //oswietlenie czolowe - przod
TButton btHeadSignals12;
TButton btHeadSignals13;
TButton btHeadSignals21; //oswietlenie czolowe - tyl
TButton btHeadSignals22;
TButton btHeadSignals23;
TSubModel *smMechanik0; //Ra: mechanik wbudowany w model jako submodel?
TSubModel *smMechanik1; //mechanik od strony sprzęgu 1
double enginevolume; //MC: pomocnicze zeby gladziej silnik buczal
int iAxles; //McZapkie: to potem mozna skasowac i zastapic iNumAxles
double dRailLength;
double dRailPosition[MaxAxles]; //licznik pozycji osi w/m szyny
double dWheelsPosition[MaxAxles]; //pozycja osi w/m srodka pojazdu
TRealSound rsStukot[MaxAxles]; //dzwieki poszczegolnych osi //McZapkie-270202
TRealSound rsSilnik; //McZapkie-010302 - silnik
TRealSound rsWentylator; //McZapkie-030302
TRealSound rsPisk; //McZapkie-260302
TRealSound rsDerailment; //McZapkie-051202
TRealSound rsPrzekladnia;
TAdvancedSound sHorn1;
TAdvancedSound sHorn2;
TAdvancedSound sCompressor; //NBMX wrzesien 2003
TAdvancedSound sConverter;
TAdvancedSound sSmallCompressor;
TAdvancedSound sDepartureSignal;
TAdvancedSound sTurbo;
//Winger 010304
// TRealSound rsPanTup; //PSound sPantUp;
TRealSound sPantUp;
TRealSound sPantDown;
TRealSound rsDoorOpen; //Ra: przeniesione z kabiny
TRealSound rsDoorClose;
double eng_vol_act;
double eng_frq_act;
double eng_dfrq;
double eng_turbo;
void __fastcall ABuBogies();
void __fastcall ABuModelRoll();
vector3 modelShake;
bool renderme; //yB - czy renderowac
//TRealSound sBrakeAcc; //dźwięk przyspieszacza
PSound sBrakeAcc;
bool bBrakeAcc;
TRealSound rsUnbrake; //yB - odglos luzowania
float ModCamRot;
int iInventory; //flagi bitowe posiadanych submodeli (np. świateł)
void __fastcall TurnOff();
public:
int iHornWarning; //numer syreny do użycia po otrzymaniu sygnału do jazdy
bool bEnabled; //Ra: wyjechał na portal i ma być usunięty
protected:
//TTrackFollower Axle2; //dwie osie z czterech (te są protected)
//TTrackFollower Axle3; //Ra: wyłączyłem, bo kąty są liczone w Segment.cpp
int iNumAxles; //ilość osi
int CouplCounter;
AnsiString asModel;
public:
void ABuScanObjects(int ScanDir,double ScanDist);
protected:
TDynamicObject* __fastcall ABuFindObject(TTrack *Track,int ScanDir,Byte &CouplFound,double &dist);
void __fastcall ABuCheckMyTrack();
public:
int *iLights; //wskaźnik na bity zapalonych świateł (własne albo innego członu)
double fTrackBlock; //odległość do przeszkody do dalszego ruchu (wykrywanie kolizji z innym pojazdem)
TDynamicObject* __fastcall PrevAny();
TDynamicObject* __fastcall Prev();
TDynamicObject* __fastcall Next();
TDynamicObject* __fastcall NextC(int C);
double __fastcall NextDistance(double d=-1.0);
void __fastcall SetdMoveLen(double dMoveLen) {MoverParameters->dMoveLen=dMoveLen;}
void __fastcall ResetdMoveLen() {MoverParameters->dMoveLen=0;}
double __fastcall GetdMoveLen() {return MoverParameters->dMoveLen;}
int __fastcall GetPneumatic(bool front, bool red);
void __fastcall SetPneumatic(bool front, bool red);
AnsiString asName;
AnsiString __fastcall GetName()
{
return this?asName:AnsiString("");
};
TRealSound rsDiesielInc; //youBy
TRealSound rscurve; //youBy
// std::ofstream PneuLogFile; //zapis parametrow pneumatycznych
//youBy - dym
//TSmoke Smog;
//float EmR;
//vector3 smokeoffset;
TDynamicObject* __fastcall ABuScanNearestObject(TTrack *Track, double ScanDir, double ScanDist, int &CouplNr);
TDynamicObject* __fastcall GetFirstDynamic(int cpl_type);
//TDynamicObject* __fastcall GetFirstCabDynamic(int cpl_type);
void ABuSetModelShake(vector3 mShake);
//McZapkie-010302
TController *Mechanik;
TController *ctOwner; //wskażnik na obiekt zarządzający składem
bool MechInside;
//McZapkie-270202
bool Controller;
bool bDisplayCab; //czy wyswietlac kabine w train.cpp
int iCabs; //maski bitowe modeli kabin
TTrack *MyTrack; //McZapkie-030303: tor na ktorym stoi, ABu
AnsiString asBaseDir;
GLuint ReplacableSkinID[5]; //McZapkie:zmienialne nadwozie
int iAlpha; //maska przezroczystości tekstur
int iMultiTex; //<0 tekstury wskazane wpisem, >0 tekstury z przecinkami, =0 jedna
int iOverheadMask; //maska przydzielana przez AI pojazdom posiadającym pantograf, aby wymuszały jazdę bezprądową
TTractionParam tmpTraction;
double fAdjustment; //korekcja - docelowo przenieść do TrkFoll.cpp wraz z odległością od poprzedniego
__fastcall TDynamicObject();
__fastcall ~TDynamicObject();
double __fastcall TDynamicObject::Init
(//zwraca długość pojazdu albo 0, jeśli błąd
AnsiString Name, AnsiString BaseDir, AnsiString asReplacableSkin, AnsiString Type_Name,
TTrack *Track, double fDist, AnsiString DriverType, double fVel, AnsiString TrainName,
float Load, AnsiString LoadType,bool Reversed, AnsiString
);
void __fastcall AttachPrev(TDynamicObject *Object, int iType= 1);
bool __fastcall UpdateForce(double dt, double dt1, bool FullVer);
void __fastcall LoadUpdate();
bool __fastcall Update(double dt, double dt1);
bool __fastcall FastUpdate(double dt);
void __fastcall Move(double fDistance);
void __fastcall FastMove(double fDistance);
void __fastcall Render();
void __fastcall RenderAlpha();
void __fastcall RenderSounds();
inline vector3 __fastcall GetPosition() {return vPosition;};
inline vector3 __fastcall HeadPosition() {return vCoulpler[iDirection^1];}; //pobranie współrzędnych czoła
inline vector3 __fastcall RearPosition() {return vCoulpler[iDirection];}; //pobranie współrzędnych tyłu
inline vector3 __fastcall AxlePositionGet() {return iAxleFirst?Axle1.pPosition:Axle0.pPosition;};
inline vector3 __fastcall VectorFront() {return vFront;};
inline vector3 __fastcall VectorUp() {return vUp;};
inline vector3 __fastcall VectorLeft() {return vLeft;};
inline double* __fastcall Matrix() {return mMatrix.getArray();};
inline double __fastcall GetVelocity() { return MoverParameters->Vel; };
inline double __fastcall GetLength() { return MoverParameters->Dim.L; };
inline double __fastcall GetWidth() { return MoverParameters->Dim.W; };
inline TTrack* __fastcall GetTrack() { return (iAxleFirst?Axle1.GetTrack():Axle0.GetTrack()); };
//void __fastcall UpdatePos();
//McZapkie-260202
void __fastcall LoadMMediaFile(AnsiString BaseDir, AnsiString TypeName, AnsiString ReplacableSkin);
inline double __fastcall ABuGetDirection() //ABu.
{
return (Axle1.GetTrack()==MyTrack?Axle1.GetDirection():Axle0.GetDirection());
};
// inline double __fastcall ABuGetTranslation() //ABu.
// {//zwraca przesunięcie wózka względem Point1 toru
// return (Axle1.GetTrack()==MyTrack?Axle1.GetTranslation():Axle0.GetTranslation());
// };
inline double __fastcall RaDirectionGet()
{//zwraca kierunek pojazdu na torze z aktywną osą
return iAxleFirst?Axle1.GetDirection():Axle0.GetDirection();
};
inline double __fastcall RaTranslationGet()
{//zwraca przesunięcie wózka względem Point1 toru z aktywną osią
return iAxleFirst?Axle1.GetTranslation():Axle0.GetTranslation();
};
inline TTrack* __fastcall RaTrackGet()
{//zwraca tor z aktywną osią
return iAxleFirst?Axle1.GetTrack():Axle0.GetTrack();
};
void CouplersDettach(double MinDist,int MyScanDir);
void __fastcall RadioStop();
void __fastcall RaLightsSet(int head,int rear);
//void __fastcall RaAxleEvent(TEvent *e);
TDynamicObject* __fastcall FirstFind(int &coupler_nr);
float __fastcall GetEPP(); //wyliczanie sredniego cisnienia w PG
int __fastcall DirectionSet(int d); //ustawienie kierunku w składzie
int __fastcall DirectionGet() {return iDirection+iDirection-1;}; //odczyt kierunku w składzie
int DettachStatus(int dir);
int Dettach(int dir);
TDynamicObject* __fastcall Neightbour(int &dir);
void __fastcall CoupleDist();
TDynamicObject* __fastcall ControlledFind();
void __fastcall ParamSet(int what,int into);
int __fastcall RouteWish(TTrack *tr); //zapytanie do AI, po którym segmencie skrzyżowania jechać
void __fastcall DestinationSet(AnsiString to);
AnsiString __fastcall TextureTest(AnsiString &name);
void __fastcall OverheadTrack(float o);
};
//---------------------------------------------------------------------------
#endif

137
EU07.bpr Normal file
View File

@@ -0,0 +1,137 @@
<?xml version='1.0' encoding='utf-8' ?>
<!-- C++Builder XML Project -->
<PROJECT>
<MACROS>
<VERSION value="BCB.05.03"/>
<PROJECT value="D:\EU07\EU07.exe"/>
<OBJFILES value="QueryParserComp.obj McZapkie\mtable.obj McZapkie\_mover.obj
McZapkie\hamulce.obj EU07.obj dumb3d.obj Camera.obj Texture.obj World.obj
Model3d.obj MdlMngr.obj Train.obj wavread.obj Timer.obj Event.obj
MemCell.obj Logs.obj Spring.obj Button.obj Globals.obj Gauge.obj
AnimModel.obj Ground.obj TrkFoll.obj Segment.obj Sound.obj AdvSound.obj
Track.obj DynObj.obj RealSound.obj EvLaunch.obj FadeSound.obj Traction.obj
TractionPower.obj parser.obj sky.obj AirCoupler.obj opengl\glew.obj
ResourceManager.obj VBO.obj TextureDDS.obj opengl\ARB_Multisample.obj
Float3d.obj Classes.obj Driver.obj Names.obj Console.obj Mover.obj
Console\PoKeys55.obj Forth.obj Console\LPT.obj"/>
<RESFILES value="EU07.res"/>
<IDLFILES value=""/>
<IDLGENFILES value=""/>
<DEFFILE value=""/>
<RESDEPEN value="$(RESFILES)"/>
<LIBFILES value="opengl\glut32.lib DirectX\Dsound.lib"/>
<LIBRARIES value="dclocx50.bpi bcbsmp50.bpi VCLX50.lib bcbsmp50.lib Vcl50.lib"/>
<SPARELIBS value="Vcl50.lib bcbsmp50.lib VCLX50.lib bcbsmp50.bpi dclocx50.bpi"/>
<PACKAGES value="Vcl50.bpi Vclx50.bpi"/>
<PATHCPP value=".;opengl;Console"/>
<PATHPAS value=".;McZapkie"/>
<PATHRC value=".;"/>
<PATHASM value=".;"/>
<DEBUGLIBPATH value="$(BCB)\lib\debug"/>
<RELEASELIBPATH value="$(BCB)\lib\release"/>
<LINKER value="tlink32"/>
<USERDEFINES value="GLEW_STATIC;_DEBUG"/>
<SYSDEFINES value="NO_STRICT;_RTLDLL"/>
<MAINSOURCE value="EU07.cpp"/>
<INCLUDEPATH value="Console;opengl;McZapkie;$(BCB)\include;$(BCB)\include\vcl"/>
<LIBPATH value="Console;opengl;McZapkie;$(BCB)\lib\obj;$(BCB)\lib"/>
<WARNINGS value="-w-par"/>
</MACROS>
<OPTIONS>
<IDLCFLAGS value="-IConsole -Iopengl -IMcZapkie -I$(BCB)\include -I$(BCB)\include\vcl
-src_suffix cpp -DGLEW_STATIC -D_DEBUG -boa"/>
<CFLAG1 value="-O2 -H=$(BCB)\lib\vcl50.csm -Hc -Vx -Ve -X- -r- -a1 -6 -b- -k -y -v -vi-
-c -tW -tWM"/>
<PFLAGS value="-$Y+ -$W -$O- -v -JPHNE -M"/>
<RFLAGS value=""/>
<AFLAGS value="/mx /w2 /zi"/>
<LFLAGS value="-D&quot;&quot; -aa -Tpe -x -Gn -v"/>
</OPTIONS>
<LINKER>
<ALLOBJ value="c0w32.obj Memmgr.Lib sysinit.obj $(OBJFILES)"/>
<ALLRES value="$(RESFILES)"/>
<ALLLIB value="$(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib"/>
</LINKER>
<IDEOPTIONS>
[Version Info]
IncludeVerInfo=1
AutoIncBuild=0
MajorVer=15
MinorVer=3
Release=1166
Build=469
Debug=1
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1045
CodePage=1250
[Version Info Keys]
CompanyName=EU07 Team
FileDescription=MaSzyna EU07-424
FileVersion=15.3.1166.469
InternalName=9th by Ra + SPKS + MP
LegalCopyright=
LegalTrademarks=
OriginalFilename=eu07.exe
ProductName=MaSzyna EU07-424
ProductVersion=15.3
Comments=
[HistoryLists\hlIncludePath]
Count=1
Item0=Console;opengl;McZapkie;$(BCB)\include;$(BCB)\include\vcl
[HistoryLists\hlLibraryPath]
Count=1
Item0=Console;opengl;McZapkie;$(BCB)\lib\obj;$(BCB)\lib
[HistoryLists\hlDebugSourcePath]
Count=2
Item0=McZapkie\
Item1=$(BCB)\source\vcl
[HistoryLists\hlConditionals]
Count=8
Item0=GLEW_STATIC;_DEBUG
Item1=GLEW_STATIC;_DEBUG;USE_VBO
Item2=GLEW_STATIC;_DEBUG;_USE_OLD_RW_STL
Item3=GLEW_STATIC
Item4=GLEW_STATIC;USE_VERTEX_ARRAYS;_DEBUG
Item5=GLEW_STATIC;USE_VERTEX_ARRAYS
Item6=GLEW_STATIC;_DEBUG;USE_VERTEX_ARRAYS
Item7=_DEBUG
[HistoryLists\hlFinalOutputDir]
Count=2
Item0=D:\EU07\
Item1=E:\EU07\
[Debugging]
DebugSourceDirs=McZapkie\
[Parameters]
RunParams=
HostApplication=
RemoteHost=
RemotePath=
RemoteDebug=0
[Compiler]
ShowInfoMsgs=0
LinkDebugVcl=0
LinkCGLIB=0
[CORBA]
AddServerUnit=1
AddClientUnit=1
PrecompiledHeaders=1
[Language]
ActiveLang=
ProjectLang=
RootDir=
</IDEOPTIONS>
</PROJECT>

725
EU07.cpp Normal file
View File

@@ -0,0 +1,725 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
*/
#include "opengl/glew.h"
#include "opengl/glut.h"
#include "opengl/ARB_Multisample.h"
#include "system.hpp"
#include "classes.hpp"
#include "Globals.h"
#include "Console.h"
#include "QueryParserComp.hpp"
#include "Mover.h"
#include "Logs.h"
#pragma hdrstop
#include <dsound.h> //_clear87() itp.
USERES("EU07.res");
USEUNIT("dumb3d.cpp");
USEUNIT("Camera.cpp");
USEUNIT("Texture.cpp");
USEUNIT("World.cpp");
USELIB("opengl\glut32.lib");
USEUNIT("Model3d.cpp");
USEUNIT("MdlMngr.cpp");
USEUNIT("Train.cpp");
USEUNIT("wavread.cpp");
USEUNIT("Timer.cpp");
USEUNIT("Event.cpp");
USEUNIT("MemCell.cpp");
USEUNIT("Logs.cpp");
USELIB("DirectX\Dsound.lib");
USEUNIT("Spring.cpp");
USEUNIT("Button.cpp");
USEUNIT("Globals.cpp");
USEUNIT("Gauge.cpp");
USEUNIT("AnimModel.cpp");
USEUNIT("Ground.cpp");
USEUNIT("TrkFoll.cpp");
USEUNIT("Segment.cpp");
USEUNIT("Sound.cpp");
USEUNIT("AdvSound.cpp");
USEUNIT("Track.cpp");
USEUNIT("DynObj.cpp");
USEUNIT("RealSound.cpp");
USEUNIT("EvLaunch.cpp");
USEUNIT("QueryParserComp.pas");
USEUNIT("FadeSound.cpp");
USEUNIT("Traction.cpp");
USEUNIT("TractionPower.cpp");
USEUNIT("parser.cpp");
USEUNIT("sky.cpp");
USEUNIT("AirCoupler.cpp");
USEUNIT("opengl\glew.c");
USEUNIT("ResourceManager.cpp");
USEUNIT("VBO.cpp");
USEUNIT("McZapkie\mtable.pas");
USEUNIT("TextureDDS.cpp");
USEUNIT("opengl\ARB_Multisample.cpp");
USEUNIT("Float3d.cpp");
USEUNIT("Classes.cpp");
USEUNIT("Driver.cpp");
USEUNIT("Names.cpp");
USEUNIT("Console.cpp");
USEUNIT("Mover.cpp");
USEUNIT("McZapkie\_mover.pas");
USEUNIT("McZapkie\hamulce.pas");
USEUNIT("Console\PoKeys55.cpp");
USEUNIT("Forth.cpp");
USEUNIT("Console\LPT.cpp");
//---------------------------------------------------------------------------
#include "World.h"
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
TWorld World;
//bool active=TRUE; //window active flag set to TRUE by default
bool fullscreen=TRUE; //fullscreen flag set to fullscreen mode by default
int WindowWidth= 800;
int WindowHeight= 600;
int Bpp= 32;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
//#include "dbgForm.h"
//---------------------------------------------------------------------------
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
_clear87();
_control87(MCW_EM,MCW_EM);
glewInit();
//hunter-271211: przeniesione
//AllocConsole();
//SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);
// ShaXbee-121209: Wlaczenie obslugi tablic wierzcholkow
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Global::pWorld=&World; //Ra: wskaŸnik potrzebny do usuwania pojazdów
return World.Init(hWnd,hDC); //true jeœli wszystko pójdzie dobrze
}
//---------------------------------------------------------------------------
GLvoid ReSizeGLScene(GLsizei width,GLsizei height) // resize and initialize the GL Window
{
WindowWidth=width;
WindowHeight=height;
if (height==0) // prevent a divide by zero by
height=1; // making height equal one
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // select the Projection Matrix
glLoadIdentity(); // reset the Projection Matrix
//calculate the aspect ratio of the window
gluPerspective(45.0f,(GLdouble)width/(GLdouble)height,0.2f,2500.0f);
glMatrixMode(GL_MODELVIEW); // select the Modelview Matrix
glLoadIdentity(); // reset the Modelview Matrix
}
//---------------------------------------------------------------------------
GLvoid KillGLWindow(GLvoid) // properly kill the window
{
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // are we able to release the DC and RC contexts?
{
ErrorLog("Fail: window releasing");
MessageBox(NULL,"Release of DC and RC failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // are we able to delete the RC?
{
ErrorLog("Fail: rendering context releasing");
MessageBox(NULL,"Release rendering context failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // set RC to NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // are we able to release the DC?
{
ErrorLog("Fail: device context releasing");
MessageBox(NULL,"Release device context failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // set DC to NULL
}
if (hWnd && !DestroyWindow(hWnd)) // are we able to destroy the window?
{
ErrorLog("Fail: window destroying");
MessageBox(NULL,"Could not release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // set hWnd to NULL
}
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // if so switch back to the desktop
ShowCursor(TRUE); // show mouse pointer
}
// KillFont();
}
/* This code creates our OpenGL Window. Parameters are: *
* title - title to appear at the top of the window *
* width - width of the GL Window or fullscreen mode *
* height - height of the GL Window or fullscreen mode *
* bits - number of bits to use for color (8/16/24/32) *
* fullscreenflag - use fullscreen mode (TRUE) or windowed mode (FALSE) */
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // holds the results after searching for a match
HINSTANCE hInstance; // holds the instance of the application
WNDCLASS wc; // windows class structure
DWORD dwExStyle; // window extended style
DWORD dwStyle; // window style
RECT WindowRect; // grabs rectangle upper left / lower right values
WindowRect.left=(long)0; // set left value to 0
WindowRect.right=(long)width; // set right value to requested width
WindowRect.top=(long)0; // set top value to 0
WindowRect.bottom=(long)height; // set bottom value to requested height
fullscreen=fullscreenflag; // set the global fullscreen flag
hInstance =GetModuleHandle(NULL); // grab an instance for our window
wc.style =CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // redraw on size, and own DC for window.
wc.lpfnWndProc =(WNDPROC) WndProc; // wndproc handles messages
wc.cbClsExtra =0; // no extra window data
wc.cbWndExtra =0; // no extra window data
wc.hInstance =hInstance; // set the instance
wc.hIcon =LoadIcon(NULL, IDI_WINLOGO); // load the default icon
wc.hCursor =LoadCursor(NULL, IDC_ARROW); // load the arrow pointer
wc.hbrBackground=NULL; // no background required for GL
wc.lpszMenuName =NULL; // we don't want a menu
wc.lpszClassName="EU07"; //nazwa okna do komunikacji zdalnej // Set The Class Name
if (!arbMultisampleSupported) //tylko dla pierwszego okna
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
ErrorLog("Fail: window class registeration");
MessageBox(NULL,"Failed to register the window class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // device mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // makes sure memory's cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // size of the devmode structure
//tolaris-240403: poprawka na odswiezanie monitora
// locate primary monitor...
if (Global::bAdjustScreenFreq)
{
POINT point; point.x=0; point.y=0;
MONITORINFOEX monitorinfo; monitorinfo.cbSize=sizeof(MONITORINFOEX);
::GetMonitorInfo( ::MonitorFromPoint(point,MONITOR_DEFAULTTOPRIMARY),&monitorinfo);
// ..and query for highest supported refresh rate
unsigned int refreshrate=0;
int i=0;
while (::EnumDisplaySettings(monitorinfo.szDevice,i,&dmScreenSettings))
{
if (i>0)
if (dmScreenSettings.dmPelsWidth==(unsigned int)width)
if (dmScreenSettings.dmPelsHeight==(unsigned int)height)
if (dmScreenSettings.dmBitsPerPel==(unsigned int)bits)
if (dmScreenSettings.dmDisplayFrequency>refreshrate)
refreshrate=dmScreenSettings.dmDisplayFrequency;
++i;
}
// fill refresh rate info for screen mode change
dmScreenSettings.dmDisplayFrequency=refreshrate;
dmScreenSettings.dmFields=DM_DISPLAYFREQUENCY;
}
dmScreenSettings.dmPelsWidth =width; // selected screen width
dmScreenSettings.dmPelsHeight=height; // selected screen height
dmScreenSettings.dmBitsPerPel=bits; // selected bits per pixel
dmScreenSettings.dmFields=dmScreenSettings.dmFields|DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try to set selected mode and get results. NOTE: CDS_FULLSCREEN gets rid of start bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If the mode fails, offer two options. Quit or use windowed mode.
ErrorLog("Fail: full screen");
if (MessageBox(NULL,"The requested fullscreen mode is not supported by\nyour video card. Use windowed mode instead?","EU07",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
Error("Program will now close.");
return FALSE; // Return FALSE
}
}
}
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // Windows Style
}
AdjustWindowRectEx(&WindowRect,dwStyle,FALSE,dwExStyle); // Adjust Window To True Requested Size
// Create The Window
if (NULL==(hWnd=CreateWindowEx(dwExStyle, // Extended Style For The Window
"EU07", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
ErrorLog("Fail: window creation");
MessageBox(NULL,"Window creation error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
24, // 32Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
if (NULL==(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
ErrorLog("Fail: device context");
MessageBox(NULL,"Can't create a GL device context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
/*
Our first pass, Multisampling hasn't been created yet, so we create a window normally
If it is supported, then we're on our second pass
that means we want to use our pixel format for sampling
so set PixelFormat to arbMultiSampleformat instead
*/
if (!arbMultisampleSupported)
{
if (NULL==(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
ErrorLog("Fail: pixelformat");
MessageBox(NULL,"Can't find a suitable pixelformat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
}
else
PixelFormat=arbMultisampleFormat;
if (!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
ErrorLog("Fail: pixelformat");
MessageBox(NULL,"Can't set the pixelformat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (NULL==(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
ErrorLog("Fail: OpenGL rendering context creation");
MessageBox(NULL,"Can't create a GL rendering context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
ErrorLog("Fail: OpenGL rendering context activation");
MessageBox(NULL,"Can't activate the GL rendering context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
/*
Now that our window is created, we want to queary what samples are available
we call our InitMultiSample window
if we return a valid context, we want to destroy our current window
and create a new one using the multisample interface.
*/
if (Global::iMultisampling)
if (!arbMultisampleSupported)
if ((Global::iMultisampling=InitMultisample(hInstance,hWnd,pfd,1<<Global::iMultisampling))!=0)
{
//WriteConsoleOnly("Opening second window for multisampling of "+AnsiString(Global::iMultisampling)+" samples.");
KillGLWindow(); // reset the display
return CreateGLWindow(title,width,height,bits,fullscreenflag); //rekurencja
}
ShowWindow(hWnd,SW_SHOW); // show the window
SetForegroundWindow(hWnd); // slightly higher priority
SetFocus(hWnd); // sets keyboard focus to the window
ReSizeGLScene(width, height); // set up our perspective GL screen
if (!InitGL()) // initialize our newly created GL Window
{
KillGLWindow(); // reset the display
ErrorLog("Fail: OpenGL initialization");
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // return FALSE
}
return TRUE; //success
}
static int mx=0, my=0;
static POINT mouse;
static int test= 0;
/**/
// ************ Globals ************
//
#define MYDISPLAY 1
PCOPYDATASTRUCT pDane;
LRESULT CALLBACK WndProc(HWND hWnd, //handle for this window
UINT uMsg, //message for this window
WPARAM wParam, //additional message information
LPARAM lParam) //additional message information
{
TRect rect;
switch (uMsg) //check for windows messages
{
case WM_PASTE: //[Ctrl]+[V] potrzebujemy do innych celów
return 0;
case WM_COPYDATA: //obs³uga danych przes³anych przez program steruj¹cy
pDane=(PCOPYDATASTRUCT)lParam;
if (pDane->dwData=='EU07') //sygnatura danych
World.OnCommandGet((DaneRozkaz*)(pDane->lpData));
break;
case WM_ACTIVATE: //watch for window activate message
//case WM_ACTIVATEAPP:
{//Ra: uzale¿nienie aktywnoœci od bycia na wierzchu
Global::bActive=(LOWORD(wParam)!=WA_INACTIVE);
if (Global::bInactivePause) //jeœli ma byæ pauzowanie okna w tle
if (Global::bActive)
Global::iPause&=~4; //odpauzowanie, gdy jest na pierwszym planie
else
Global::iPause|=4; //w³¹czenie pauzy, gdy nieaktywy
if (Global::bActive)
SetCursorPos(mx,my);
ShowCursor(!Global::bActive);
/*
if (!HIWORD(wParam)) //check minimization state
active=TRUE; //program is active
else
active=FALSE; //program is no longer active
*/
return 0; // return to the message loop
}
case WM_SYSCOMMAND: //intercept system commands
{
switch (wParam) //check system calls
{
case 61696: //F10
World.OnKeyDown(VK_F10);
return 0;
case SC_SCREENSAVE: //screensaver trying to start?
case SC_MONITORPOWER: //monitor trying to enter powersave?
return 0; //prevent from happening
}
break; //exit
}
case WM_CLOSE: // did we receive a close message?
{
PostQuitMessage(0); //send a quit message [Alt]+[F4]
return 0; //jump back
}
case WM_MOUSEMOVE:
{
//mx= 100;//Global::iWindowWidth/2;
//my= 100;//Global::iWindowHeight/2;
//SetCursorPos(Global::iWindowWidth/2,Global::iWindowHeight/2);
//m_x= LOWORD(lParam);
//m_y= HIWORD(lParam);
GetCursorPos(&mouse);
if (Global::bActive && ((mouse.x!=mx) || (mouse.y!=my)))
{
World.OnMouseMove(double(mouse.x-mx)*0.005,double(mouse.y-my)*0.01);
SetCursorPos(mx,my);
}
return 0; // jump back
}
case WM_KEYUP :
if (Global::bActive)
{
World.OnKeyUp(wParam);
return 0;
}
case WM_KEYDOWN :
if (Global::bActive)
{
if (wParam!=17) //bo naciœniêcia [Ctrl] nie ma po co przekazywaæ
if (wParam!=145) //[Scroll Lock] te¿ nie
World.OnKeyDown(wParam);
switch (wParam)
{
case VK_ESCAPE: //[Esc] pauzuje tylko bez Debugmode
if (DebugModeFlag) break;
case 19: //[Pause]
if (Global::iPause&1) //jeœli pauza startowa
Global::iPause&=~1; //odpauzowanie, gdy po wczytaniu mia³o nie startowaæ
else if (!(Global::iMultiplayer&2)) //w multiplayerze pauza nie ma sensu
if (!Console::Pressed(VK_CONTROL)) //z [Ctrl] to radiostop jest
//Ra: poni¿sze nie ma sensu, bo brak komunikacji natychmiast zapauzuje ponownie
//if (Global::iPause&8) //jeœli pauza zwi¹zana z brakiem komunikacji z PoKeys
// Global::iPause&=~10; //odpauzowanie pauzy PoKeys (chyba nic nie da) i ewentualnie klawiszowej równie¿
//else
Global::iPause^=2; //zmiana stanu zapauzowania
if (Global::iPause) //jak pauza
Global::iTextMode=VK_F1; //to wyœwietliæ zegar i informacjê
break;
case VK_F7:
if (DebugModeFlag)
{//siatki wyœwietlane tyko w trybie testowym
Global::bWireFrame=!Global::bWireFrame;
++Global::iReCompile; //odœwie¿yæ siatki
//Ra: jeszcze usun¹æ siatki ze skompilowanych obiektów!
}
break;
}
}
return 0; // jump back
case WM_CHAR:
{
/*
switch ((TCHAR) wParam)
{
// case 'q':
// done= true;
// KillGLWindow();
// PostQuitMessage(0);
// DestroyWindow( hWnd );
// break;
};
*/
return 0;
}
case WM_SIZE: //resize the OpenGL window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
if (GetWindowRect(hWnd,&rect))
{//Ra: zmiana rozmiaru okna bez przesuwania myszy
//mx=WindowWidth/2+rect.left; // horizontal position
//my=WindowHeight/2+rect.top; // vertical position
//SetCursorPos(mx,my);
}
return 0; //jump back
}
case WM_MOVE: //przesuwanie okna?
{
mx=WindowWidth/2+LOWORD(lParam); // horizontal position
my=WindowHeight/2+HIWORD(lParam); // vertical position
//SetCursorPos(mx,my);
break;
}
case WM_PAINT:
{//odrysowanie okna
break;
}
//case WM_ERASEBKGND: //Process this message to keep Windows from erasing background.
case MM_JOY1BUTTONDOWN:
{
//WriteLog("Joystick button "+AnsiString(wParam));
break;
}
case WM_CREATE:
/* Capture the joystick. If this fails, beep and display
* error, then quit.
*/
if (joySetCapture(hWnd,JOYSTICKID1,0,FALSE))
{
//MessageBeep(MB_ICONEXCLAMATION);
//MessageBox(hWnd,"Couldn't capture the joystick",NULL,MB_OK|MB_ICONEXCLAMATION);
//return -1;
}
break;
}
// pass all unhandled messages to DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
};
int WINAPI WinMain( HINSTANCE hInstance, //instance
HINSTANCE hPrevInstance, //previous instance
LPSTR lpCmdLine, //command line parameters
int nCmdShow) //window show state
{
MSG msg; //windows message structure
BOOL done=FALSE; //bool variable to exit loop
fullscreen=true;
DecimalSeparator= '.';
/* //Ra: tutaj to nie dzia³a - zwraca NULL
//najpierw ustalmy wersjê OpenGL
AnsiString glver=((char*)glGetString(GL_VERSION));
while (glver.LastDelimiter(".")>glver.Pos("."))
glver=glver.SubString(1,glver.LastDelimiter(".")-1); //obciêcie od drugiej kropki
try {Global::fOpenGL=glver.ToDouble();} catch (...) {Global::fOpenGL=0.0;}
Global::bOpenGL_1_5=(Global::fOpenGL>=1.5);
*/
DeleteFile("errors.txt"); //usuniêcie starego
Global::LoadIniFile("eu07.ini"); //teraz dopiero mo¿na przejrzeæ plik z ustawieniami
Global::InitKeys("keys.ini"); //wczytanie mapowania klawiszy - jest na sta³e
//hunter-271211: ukrywanie konsoli
if (Global::iWriteLogEnabled&2)
{
AllocConsole();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);
}
AnsiString str=lpCmdLine; //parametry uruchomienia
if (!str.IsEmpty())
{//analizowanie parametrów
TQueryParserComp *Parser;
Parser=new TQueryParserComp(NULL);
Parser->TextToParse=lpCmdLine;
Parser->First();
while (!Parser->EndOfFile)
{
str=Parser->GetNextSymbol().LowerCase();
if (str==AnsiString("-s"))
{//nazwa scenerii
str=Parser->GetNextSymbol().LowerCase();
strcpy(Global::szSceneryFile,str.c_str());
}
else if (str==AnsiString("-v"))
{//nazwa wybranego pojazdu
str=Parser->GetNextSymbol().LowerCase();
Global::asHumanCtrlVehicle=str;
}
else if (str==AnsiString("-modifytga"))
{//wykonanie modyfikacji wszystkich plików TGA
Global::iModifyTGA=-1; //specjalny tryb wykonania totalnej modyfikacji
}
else if (str==AnsiString("-e3d"))
{//wygenerowanie wszystkich plików E3D
if (Global::iConvertModels>0)
Global::iConvertModels=-Global::iConvertModels; //specjalny tryb
else
Global::iConvertModels=-7; //z optymalizacj¹, bananami i prawid³owym Opacity
}
else
Error("Program usage: EU07 [-s sceneryfilepath] [-v vehiclename] [-modifytga] [-e3d]",!Global::iWriteLogEnabled);
}
delete Parser; //ABu 050205: tego wczesniej nie bylo
}
/* MC: usunalem tymczasowo bo sie gryzlo z nowym parserem - 8.6.2003
AnsiString csp=AnsiString(Global::szSceneryFile);
csp=csp.Delete(csp.Pos(AnsiString(strrchr(Global::szSceneryFile,'/')))+1,csp.Length());
Global::asCurrentSceneryPath=csp;
*/
fullscreen=Global::bFullScreen;
WindowWidth=Global::iWindowWidth;
WindowHeight=Global::iWindowHeight;
Bpp=Global::iBpp;
if (Bpp!=32) Bpp=16;
//create our OpenGL window
if (!CreateGLWindow(Global::asHumanCtrlVehicle.c_str(),WindowWidth,WindowHeight,Bpp,fullscreen))
return 0; //quit if window was not created
SetForegroundWindow(hWnd);
//McZapkie: proba przeplukania klawiatury
Console *pConsole=new Console(); //Ra: nie wiem, czy ma to sens, ale jakoœ zainicjowac trzeba
while (Console::Pressed(VK_F10))
Error("Keyboard buffer problem - press F10"); //na Windows 98 lubi siê to pojawiaæ
int iOldSpeed, iOldDelay;
SystemParametersInfo(SPI_GETKEYBOARDSPEED,0,&iOldSpeed,0);
SystemParametersInfo(SPI_GETKEYBOARDDELAY,0,&iOldDelay,0);
SystemParametersInfo(SPI_SETKEYBOARDSPEED,20,NULL,0);
//SystemParametersInfo(SPI_SETKEYBOARDDELAY,10,NULL,0);
if (!joyGetNumDevs())
WriteLog("No joystick");
if (Global::iModifyTGA<0)
{//tylko modyfikacja TGA, bez uruchamiania symulacji
Global::iMaxTextureSize=64; //¿eby nie zamulaæ pamiêci
World.ModifyTGA(); //rekurencyjne przegl¹danie katalogów
}
else
{if (Global::iConvertModels<0)
{Global::iConvertModels=-Global::iConvertModels;
World.CreateE3D("models\\"); //rekurencyjne przegl¹danie katalogów
World.CreateE3D("dynamic\\",true);
} //po zrobieniu E3D odpalamy normalnie sceneriê, by j¹ zobaczyæ
//else
//{//g³ówna pêtla programu
Console::On(); //w³¹czenie konsoli
while (!done) //loop that runs while done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //is there a message waiting?
{
if (msg.message==WM_QUIT) //have we received a quit message?
done=TRUE; //if so
else //if not, deal with window messages
{
//if (msg.message==WM_CHAR)
//World.OnKeyDown(msg.wParam);
TranslateMessage(&msg); //translate the message
DispatchMessage(&msg); //dispatch the message
}
}
else //if there are no messages
{
//draw the scene, watch for quit messages
//DrawGLScene()
//if (!pause)
//if (Global::bInactivePause?Global::bActive:true) //tak nie, bo spada z góry
if (World.Update()) // Was There A Quit Received?
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
else
done=true; //[F10] or DrawGLScene signalled a quit
}
}
Console::Off(); //wy³¹czenie konsoli (komunikacji zwrotnej)
}
SystemParametersInfo(SPI_SETKEYBOARDSPEED,iOldSpeed,NULL,0);
SystemParametersInfo(SPI_SETKEYBOARDDELAY,iOldDelay,NULL,0);
delete pConsole; //deaktywania sterownika
//shutdown
KillGLWindow(); //kill the window
return (msg.wParam); //exit the program
}

BIN
EU07.res Normal file

Binary file not shown.

184
EvLaunch.cpp Normal file
View File

@@ -0,0 +1,184 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include "system.hpp"
#pragma hdrstop
#include "mtable.hpp"
#include "Timer.h"
#include "Globals.h"
#include "EvLaunch.h"
#include "Event.h"
#include "Usefull.h"
#include "MemCell.h"
#include "parser.h"
#include "Console.h"
//---------------------------------------------------------------------------
__fastcall TEventLauncher::TEventLauncher()
{//ustawienie pocz¹tkowych wartoœci dla wszystkich zmiennych
iKey=0;
DeltaTime=-1;
UpdatedTime=0;
fVal1=fVal2=0;
szText=NULL;
iHour=iMinute=-1; //takiego czasu nigdy nie bêdzie
dRadius=0;
Event1=Event2=NULL;
MemCell=NULL;
iCheckMask=0;
}
__fastcall TEventLauncher::~TEventLauncher()
{
SafeDeleteArray(szText);
}
void __fastcall TEventLauncher::Init()
{
}
bool __fastcall TEventLauncher::Load(cParser *parser)
{//wczytanie wyzwalacza zdarzeñ
AnsiString str;
std::string token;
parser->getTokens();
*parser >> dRadius; //promieñ dzia³ania
if (dRadius>0.0)
dRadius*=dRadius; //do kwadratu, pod warunkiem, ¿e nie jest ujemne
parser->getTokens(); //klawisz steruj¹cy
*parser >> token;
str=AnsiString(token.c_str());
if (str!="none")
{
if (str.Length()==1)
iKey=VkKeyScan(str[1]); //jeden znak jest konwertowany na kod klawisza
else
iKey=str.ToIntDef(0); //a jak wiêcej, to jakby numer klawisza jest
}
parser->getTokens();
*parser >> DeltaTime;
if (DeltaTime<0)
DeltaTime=-DeltaTime; //dla ujemnego zmieniamy na dodatni
else if (DeltaTime>0)
{//wartoœæ dodatnia oznacza wyzwalanie o okreœlonej godzinie
iMinute=int(DeltaTime)%100; //minuty s¹ najm³odszymi cyframi dziesietnymi
iHour=int(DeltaTime-iMinute)/100; //godzina to setki
DeltaTime=0; //bez powtórzeñ
WriteLog("EventLauncher at "+IntToStr(iHour)+":"+IntToStr(iMinute)); //wyœwietlenie czasu
}
parser->getTokens();
*parser >> token;
asEvent1Name=AnsiString(token.c_str()); //pierwszy event
parser->getTokens();
*parser >> token;
asEvent2Name=AnsiString(token.c_str()); //drugi event
if ((asEvent2Name=="end")||(asEvent2Name=="condition"))
{//drugiego eventu mo¿e nie byæ, bo s¹ z tym problemy, ale ciii...
str=asEvent2Name; //rozpoznane s³owo idzie do dalszego przetwarzania
asEvent2Name="none"; //a drugiego eventu nie ma
}
else
{//gdy s¹ dwa eventy
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
}
if (str==AnsiString("condition"))
{//obs³uga wyzwalania warunkowego
parser->getTokens();
*parser >> token;
asMemCellName=AnsiString(token.c_str());
parser->getTokens();
*parser >> token;
SafeDeleteArray(szText);
szText=new char[256];
strcpy(szText,token.c_str());
if (token.compare("*")!=0) //*=nie braæ command pod uwagê
iCheckMask|=conditional_memstring;
parser->getTokens();
*parser >> token;
if (token.compare("*")!=0) //*=nie braæ wartoœci 1. pod uwagê
{
iCheckMask|=conditional_memval1;
str=AnsiString(token.c_str());
fVal1=str.ToDouble();
}
else fVal1=0;
parser->getTokens();
*parser >> token;
if (token.compare("*")!=0) //*=nie braæ wartoœci 2. pod uwagê
{
iCheckMask|=conditional_memval2;
str=AnsiString(token.c_str());
fVal2=str.ToDouble();
}
else fVal2=0;
parser->getTokens(); //s³owo zamykaj¹ce
*parser >> token;
}
return true;
};
bool __fastcall TEventLauncher::Render()
{//"renderowanie" wyzwalacza
bool bCond=false;
if (iKey!=0)
{
if (Global::bActive) //tylko jeœli okno jest aktywne
bCond=(Console::Pressed(iKey)); //czy klawisz wciœniêty
}
if (DeltaTime>0)
{
if (UpdatedTime>DeltaTime)
{
UpdatedTime=0; //naliczanie od nowa
bCond=true;
}
else
UpdatedTime+=Timer::GetDeltaTime(); //aktualizacja naliczania czasu
}
else
{//jeœli nie cykliczny, to sprawdziæ czas
if (GlobalTime->hh==iHour)
{if (GlobalTime->mm==iMinute)
{//zgodnoϾ czasu uruchomienia
if (UpdatedTime<10)
{
UpdatedTime=20; //czas do kolejnego wyzwolenia?
bCond=true;
}
}
}
else
UpdatedTime=1;
}
if (bCond) //jeœli spe³niony zosta³ warunek
{
if ((iCheckMask!=0)&&MemCell) //sprawdzanie warunku na komórce pamiêci
bCond=MemCell->Compare(szText,fVal1,fVal2,iCheckMask);
}
return bCond; //sprawdzanie dRadius w Ground.cpp
}
bool __fastcall TEventLauncher::IsGlobal()
{//sprawdzenie, czy jest globalnym wyzwalaczem czasu
if (DeltaTime==0)
if (iHour>=0)
if (iMinute>=0)
if (dRadius<0.0) //bez ograniczenia zasiêgu
return true;
return false;
};
//---------------------------------------------------------------------------
#pragma package(smart_init)

36
EvLaunch.h Normal file
View File

@@ -0,0 +1,36 @@
//---------------------------------------------------------------------------
#ifndef EvLaunchH
#define EvLaunchH
#include "Classes.h"
class TEventLauncher
{
private:
int iKey;
double DeltaTime;
double UpdatedTime;
double fVal1;
double fVal2;
char *szText;
int iHour,iMinute; //minuta uruchomienia
public:
double dRadius;
AnsiString asEvent1Name;
AnsiString asEvent2Name;
AnsiString asMemCellName;
TEvent *Event1;
TEvent *Event2;
TMemCell *MemCell;
int iCheckMask;
__fastcall TEventLauncher();
__fastcall ~TEventLauncher();
void __fastcall Init();
bool __fastcall Load(cParser *parser);
bool __fastcall Render();
bool __fastcall IsGlobal();
};
//---------------------------------------------------------------------------
#endif

626
Event.cpp Normal file
View File

@@ -0,0 +1,626 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Event.h"
#include "parser.h"
#include "Timer.h"
#include "Usefull.h"
#include "MemCell.h"
#include "Globals.h"
#include "Ground.h"
#pragma package(smart_init)
__fastcall TEvent::TEvent(AnsiString m)
{
//asName=""; //czy nazwa eventu jest niezbêdna w tym przypadku? chyba nie
evNext=evNext2=NULL;
bEnabled=false; //false dla eventów u¿ywanych do skanowania sygna³ów (nie dodawane do kolejki)
asNodeName=m; //nazwa obiektu powi¹zanego
iQueued=0; //nie zosta³ dodany do kolejki
//bIsHistory=false;
fDelay=0;
fStartTime=0; //0 nie ma sensu
Type=m.IsEmpty()?tp_Unknown:tp_GetValues; //utworzenie niejawnego odczytu komórki pamiêci w torze
for (int i=0;i<13;i++)
Params[i].asPointer=NULL;
evJoined=NULL; //nie ma kolejnego z t¹ sam¹ nazw¹, usuwane s¹ wg listy Next2
Activator=NULL;
iFlags=0;
//event niejawny jest tworzony przed faz¹ InitEvents, która podmienia nazwê komórki pamiêci na wskaŸnik
//Current->Params[8].asGroundNode=m; //to siê ustawi w InitEvents
//Current->Params[9].asMemCell=m->MemCell;
fRandomDelay=0.0; //standardowo nie bêdzie dodatkowego losowego opóŸnienia
};
__fastcall TEvent::~TEvent()
{
switch (Type)
{//sprz¹tanie
case tp_Multiple:
//SafeDeleteArray(Params[9].asText); //nie usuwaæ - nazwa obiektu powi¹zanego zamieniana na wskaŸnik
if (iFlags&conditional_memstring) //o ile jest ³añcuch do porównania w memcompare
SafeDeleteArray(Params[10].asText);
break;
case tp_UpdateValues:
case tp_AddValues:
SafeDeleteArray(Params[0].asText);
if (iFlags&conditional_memstring) //o ile jest ³añcuch do porównania w memcompare
SafeDeleteArray(Params[10].asText);
break;
case tp_Animation: //nic
//SafeDeleteArray(Params[9].asText); //nie usuwaæ - nazwa jest zamieniana na wskaŸnik do submodelu
if (Params[0].asInt==4) //jeœli z pliku VMD
delete[] Params[8].asPointer; //zwolniæ obszar
case tp_GetValues: //nic
break;
}
evJoined=NULL; //nie usuwaæ podczepionych tutaj
};
void __fastcall TEvent::Init()
{
};
void __fastcall TEvent::Conditions(cParser* parser,AnsiString s)
{//przetwarzanie warunków, wspólne dla Multiple i UpdateValues
if (s=="condition")
{//jesli nie "endevent"
std::string token;
AnsiString str;
if (!asNodeName.IsEmpty())
{//podczepienie ³añcucha, jeœli nie jest pusty
Params[9].asText=new char[asNodeName.Length()+1]; //usuwane i zamieniane na wskaŸnik
strcpy(Params[9].asText,asNodeName.c_str());
}
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str==AnsiString("trackoccupied"))
iFlags|=conditional_trackoccupied;
else if (str==AnsiString("trackfree"))
iFlags|=conditional_trackfree;
else if (str==AnsiString("propability"))
{
iFlags|=conditional_propability;
parser->getTokens();
*parser >> Params[10].asdouble;
}
else if (str==AnsiString("memcompare"))
{
iFlags|=conditional_memcompare;
parser->getTokens(1,false); //case sensitive
*parser >> token;
str=AnsiString(token.c_str());
if (str!="*") //"*" - nie brac command pod uwage
{//zapamiêtanie ³añcucha do porównania
Params[10].asText=new char[255];
strcpy(Params[10].asText,str.c_str());
iFlags|=conditional_memstring;
}
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str!="*") //"*" - nie brac val1 pod uwage
{
Params[11].asdouble=str.ToDouble();
iFlags|=conditional_memval1;
}
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str!=AnsiString("*")) //"*" - nie brac val2 pod uwage
{
Params[12].asdouble=str.ToDouble();
iFlags|=conditional_memval2;
}
}
parser->getTokens(); *parser >> token;
s=AnsiString(token.c_str()); //ewentualnie dalej losowe opóŸnienie
}
if (s=="randomdelay")
{//losowe opóŸnienie
std::string token;
parser->getTokens();
*parser >> fRandomDelay; //Ra 2014-03-11
parser->getTokens(); *parser >> token; //endevent
}
};
void __fastcall TEvent::Load(cParser* parser,vector3 *org)
{
int i;
int ti;
double tf;
std::string token;
AnsiString str;
char *ptr;
bEnabled=true; //zmieniane na false dla eventów u¿ywanych do skanowania sygna³ów
parser->getTokens();
*parser >> token;
asName=AnsiString(token.c_str()).LowerCase(); //u¿ycie parametrów mo¿e dawaæ wielkie
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str==AnsiString("exit"))
Type=tp_Exit;
else if (str==AnsiString("updatevalues"))
Type=tp_UpdateValues;
else if (str==AnsiString("getvalues"))
Type=tp_GetValues;
else if (str==AnsiString("putvalues"))
Type=tp_PutValues;
else if (str==AnsiString("disable"))
Type=tp_Disable;
else if (str==AnsiString("sound"))
Type=tp_Sound;
else if (str==AnsiString("velocity"))
Type=tp_Velocity;
else if (str==AnsiString("animation"))
Type=tp_Animation;
else if (str==AnsiString("lights"))
Type=tp_Lights;
else if (str==AnsiString("visible"))
Type=tp_Visible; //zmiana wyœwietlania obiektu
else if (str==AnsiString("switch"))
Type=tp_Switch;
else if (str==AnsiString("dynvel"))
Type=tp_DynVel;
else if (str==AnsiString("trackvel"))
Type=tp_TrackVel;
else if (str==AnsiString("multiple"))
Type=tp_Multiple;
else if (str==AnsiString("addvalues"))
Type=tp_AddValues;
else if (str==AnsiString("copyvalues"))
Type=tp_CopyValues;
else if (str==AnsiString("whois"))
Type=tp_WhoIs;
else if (str==AnsiString("logvalues"))
Type=tp_LogValues;
else if (str==AnsiString("voltage"))
Type=tp_Voltage; //zmiana napiêcia w zasilaczu (TractionPowerSource)
else if (str==AnsiString("message"))
Type=tp_Message; //wyœwietlenie komunikatu
else if (str==AnsiString("friction"))
Type=tp_Friction; //zmiana tarcia na scenerii
else
Type=tp_Unknown;
parser->getTokens();
*parser >> fDelay;
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str!="none") asNodeName=str; //nazwa obiektu powi¹zanego
if (asName.SubString(1,5)=="none_")
Type=tp_Ignored; //Ra: takie s¹ ignorowane
switch (Type)
{
case tp_AddValues:
iFlags=update_memadd; //dodawanko
case tp_UpdateValues:
//if (Type==tp_UpdateValues) iFlags=0; //co modyfikowaæ
parser->getTokens(1,false); //case sensitive
*parser >> token;
str=AnsiString(token.c_str());
Params[0].asText=new char[str.Length()+1];
strcpy(Params[0].asText,str.c_str());
if (str!="*") //czy ma zostaæ bez zmian?
iFlags|=update_memstring;
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str!="*") //czy ma zostaæ bez zmian?
{
Params[1].asdouble=str.ToDouble();
iFlags|=update_memval1;
}
else
Params[1].asdouble=0;
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str!="*") //czy ma zostaæ bez zmian?
{
Params[2].asdouble=str.ToDouble();
iFlags|=update_memval2;
}
else
Params[2].asdouble=0;
parser->getTokens();
*parser >> token;
Conditions(parser,token.c_str()); //sprawdzanie warunków
break;
case tp_CopyValues:
Params[9].asText=NULL;
iFlags=update_memstring|update_memval1|update_memval2; //normalanie trzy
i=0;
parser->getTokens();
*parser >> token; //nazwa drugiej komórki (Ÿród³owej)
while (token.compare("endevent")!=0)
{
switch (++i)
{//znaczenie kolejnych parametrów
case 1: //nazwa drugiej komórki (Ÿród³owej)
Params[9].asText=new char[token.length()+1]; //usuwane i zamieniane na wskaŸnik
strcpy(Params[9].asText,token.c_str());
break;
case 2: //maska wartoœci
iFlags=AnsiString(token.c_str()).ToIntDef(update_memstring|update_memval1|update_memval2);
break;
}
parser->getTokens();
*parser >> token;
}
break;
case tp_WhoIs:
iFlags=update_memstring|update_memval1|update_memval2; //normalanie trzy
i=0;
parser->getTokens();
*parser >> token; //nazwa drugiej komórki (Ÿród³owej)
while (token.compare("endevent")!=0)
{
switch (++i)
{//znaczenie kolejnych parametrów
case 1: //maska wartoœci
iFlags=AnsiString(token.c_str()).ToIntDef(update_memstring|update_memval1|update_memval2);
break;
}
parser->getTokens();
*parser >> token;
}
break;
case tp_GetValues:
case tp_LogValues:
parser->getTokens(); //"endevent"
*parser >> token;
break;
case tp_PutValues:
parser->getTokens(3);
*parser >> Params[3].asdouble >> Params[4].asdouble >> Params[5].asdouble; //po³o¿enie X,Y,Z
if (org)
{//przesuniêcie
//tmp->pCenter.RotateY(aRotate.y/180.0*M_PI); //Ra 2014-11: uwzglêdnienie rotacji
Params[3].asdouble+=org->x; //wspó³rzêdne w scenerii
Params[4].asdouble+=org->y;
Params[5].asdouble+=org->z;
}
//Params[12].asInt=0;
parser->getTokens(1,false); //komendy 'case sensitive'
*parser >> token;
str=AnsiString(token.c_str());
if (str.SubString(1,19)=="PassengerStopPoint:")
{if (str.Pos("#")) str=str.SubString(1,str.Pos("#")-1); //obciêcie unikatowoœci
bEnabled=false; //nie do kolejki (dla SetVelocity te¿, ale jak jest do toru dowi¹zany)
Params[6].asCommand=cm_PassengerStopPoint;
}
else if (str=="SetVelocity")
{bEnabled=false;
Params[6].asCommand=cm_SetVelocity;
}
else if (str=="ShuntVelocity")
{bEnabled=false;
Params[6].asCommand=cm_ShuntVelocity;
}
else if (str=="SetProximityVelocity")
{bEnabled=false;
Params[6].asCommand=cm_SetProximityVelocity;
}
else if (str=="OutsideStation")
{bEnabled=false; //ma byæ skanowny, aby AI nie przekracza³o W5
Params[6].asCommand=cm_OutsideStation;
}
else
Params[6].asCommand=cm_Unknown;
Params[0].asText=new char[str.Length()+1];
strcpy(Params[0].asText,str.c_str());
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str=="none")
Params[1].asdouble=0.0;
else
try
{Params[1].asdouble=str.ToDouble();}
catch (...)
{Params[1].asdouble=0.0;
WriteLog("Error: number expected in PutValues event, found: "+str);
}
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
if (str=="none")
Params[2].asdouble=0.0;
else
try
{Params[2].asdouble=str.ToDouble();}
catch (...)
{Params[2].asdouble=0.0;
WriteLog("Error: number expected in PutValues event, found: "+str);
}
parser->getTokens();
*parser >> token;
break;
case tp_Lights:
i=0;
do
{
parser->getTokens();
*parser >> token;
if (token.compare("endevent")!=0)
{
str=AnsiString(token.c_str());
if (i<8)
Params[i].asdouble=str.ToDouble(); //teraz mo¿e mieæ u³amek
i++;
}
}
while (token.compare("endevent")!=0);
break;
case tp_Visible: //zmiana wyœwietlania obiektu
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
Params[0].asInt=str.ToInt();
parser->getTokens(); *parser >> token;
break;
case tp_Velocity:
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
Params[0].asdouble=str.ToDouble()*0.28;
parser->getTokens(); *parser >> token;
break;
case tp_Sound:
//Params[0].asRealSound->Init(asNodeName.c_str(),Parser->GetNextSymbol().ToDouble(),Parser->GetNextSymbol().ToDouble(),Parser->GetNextSymbol().ToDouble(),Parser->GetNextSymbol().ToDouble());
//McZapkie-070502: dzwiek przestrzenny (ale do poprawy)
//Params[1].asdouble=Parser->GetNextSymbol().ToDouble();
//Params[2].asdouble=Parser->GetNextSymbol().ToDouble();
//Params[3].asdouble=Parser->GetNextSymbol().ToDouble(); //polozenie X,Y,Z - do poprawy!
parser->getTokens();
*parser >> Params[0].asInt; //0: wylaczyc, 1: wlaczyc; -1: wlaczyc zapetlone
parser->getTokens(); *parser >> token;
break;
case tp_Exit:
while ((ptr=strchr(asNodeName.c_str(),'_'))!=NULL)
*ptr=' ';
parser->getTokens(); *parser >> token;
break;
case tp_Disable:
parser->getTokens(); *parser >> token;
break;
case tp_Animation:
parser->getTokens();
*parser >> token;
Params[0].asInt=0; //na razie nieznany typ
if (token.compare("rotate")==0)
{//obrót wzglêdem osi
parser->getTokens();
*parser >> token;
Params[9].asText=new char[255]; //nazwa submodelu
strcpy(Params[9].asText,token.c_str());
Params[0].asInt=1;
parser->getTokens(4);
*parser >> Params[1].asdouble >> Params[2].asdouble >> Params[3].asdouble >> Params[4].asdouble;
}
else if (token.compare("translate")==0)
{//przesuw o wektor
parser->getTokens();
*parser >> token;
Params[9].asText=new char[255]; //nazwa submodelu
strcpy(Params[9].asText,token.c_str());
Params[0].asInt=2;
parser->getTokens(4);
*parser >> Params[1].asdouble >> Params[2].asdouble >> Params[3].asdouble >> Params[4].asdouble;
}
else if (token.compare("digital")==0)
{//licznik cyfrowy
parser->getTokens();
*parser >> token;
Params[9].asText=new char[255]; //nazwa submodelu
strcpy(Params[9].asText,token.c_str());
Params[0].asInt=8;
parser->getTokens(4); //jaki ma byæ sens tych parametrów?
*parser >> Params[1].asdouble >> Params[2].asdouble >> Params[3].asdouble >> Params[4].asdouble;
}
else if (token.substr(token.length()-4,4)==".vmd") //na razie tu, mo¿e bêdzie inaczej
{//animacja z pliku VMD
TFileStream *fs=new TFileStream("models\\"+AnsiString(token.c_str()),fmOpenRead);
Params[7].asInt=fs->Size;
Params[8].asPointer=new char[fs->Size];
fs->Read(Params[8].asPointer,fs->Size); //wczytanie pliku
delete fs;
parser->getTokens();
*parser >> token;
Params[9].asText=new char[255]; //nazwa submodelu
strcpy(Params[9].asText,token.c_str());
Params[0].asInt=4; //rodzaj animacji
parser->getTokens(4);
*parser >> Params[1].asdouble >> Params[2].asdouble >> Params[3].asdouble >> Params[4].asdouble;
}
parser->getTokens(); *parser >> token;
break;
case tp_Switch:
parser->getTokens(); *parser >> Params[0].asInt;
parser->getTokens(); *parser >> token;
str=AnsiString(token.c_str());
if (str!="endevent")
{Params[1].asdouble=str.ToDouble(); //prêdkoœæ liniowa ruchu iglic
parser->getTokens(); *parser >> token;
str=AnsiString(token.c_str());
}
else
Params[1].asdouble=-1.0; //u¿yæ domyœlnej
if (str!="endevent")
{Params[2].asdouble=str.ToDouble(); //dodatkowy ruch drugiej iglicy (zamkniêcie nastawnicze)
parser->getTokens(); *parser >> token;
}
else
Params[2].asdouble=-1.0; //u¿yæ domyœlnej
break;
case tp_DynVel:
parser->getTokens();
*parser >> Params[0].asdouble; //McZapkie-090302 *0.28;
parser->getTokens(); *parser >> token;
break;
case tp_TrackVel:
parser->getTokens();
*parser >> Params[0].asdouble; //McZapkie-090302 *0.28;
parser->getTokens(); *parser >> token;
break;
case tp_Multiple:
i=0;
ti=0; //flaga dla else
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
while (str!=AnsiString("endevent") && str!=AnsiString("condition") && str!=AnsiString("randomdelay"))
{
if ((str.SubString(1,5)!="none_")?(i<8):false)
{//eventy rozpoczynaj¹ce siê od "none_" s¹ ignorowane
if (str!="else")
{Params[i].asText=new char[255];
strcpy(Params[i].asText,str.c_str());
if (ti) iFlags|=conditional_else<<i; //oflagowanie dla eventów "else"
i++;
}
else
ti=!ti; //zmiana flagi dla s³owa "else"
}
else if (i>=8)
ErrorLog("Bad event: \""+str+"\" ignored in multiple \""+asName+"\"!");
else
WriteLog("Event \""+str+"\" ignored in multiple \""+asName+"\"!");
parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
}
Conditions(parser,str); //sprawdzanie warunków
break;
case tp_Voltage: //zmiana napiêcia w zasilaczu (TractionPowerSource)
case tp_Friction: //zmiana przyczepnosci na scenerii
parser->getTokens();
*parser >> Params[0].asdouble; //Ra 2014-01-27
parser->getTokens(); *parser >> token;
break;
case tp_Message: //wyœwietlenie komunikatu
do
{parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
} while (str!="endevent");
break;
case tp_Ignored: //ignorowany
case tp_Unknown: //nieznany
do
{parser->getTokens();
*parser >> token;
str=AnsiString(token.c_str());
} while (str!="endevent");
WriteLog("Bad event: \""+asName+(Type==tp_Unknown?"\" has unknown type.":"\" is ignored."));
break;
}
};
void __fastcall 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;
}
}
//---------------------------------------------------------------------------
AnsiString __fastcall TEvent::CommandGet()
{//odczytanie komendy z eventu
switch (Type)
{//to siê wykonuje równie¿ sk³adu jad¹cego bez obs³ugi
case tp_GetValues:
return String(Params[9].asMemCell->Text());
case tp_PutValues:
return String(Params[0].asText);
}
return ""; //inne eventy siê nie licz¹
};
TCommandType __fastcall TEvent::Command()
{//odczytanie komendy z eventu
switch (Type)
{//to siê wykonuje równie¿ dla sk³adu jad¹cego bez obs³ugi
case tp_GetValues:
return Params[9].asMemCell->Command();
case tp_PutValues:
return Params[6].asCommand; //komenda zakodowana binarnie
}
return cm_Unknown; //inne eventy siê nie licz¹
};
double __fastcall TEvent::ValueGet(int n)
{//odczytanie komendy z eventu
n&=1; //tylko 1 albo 2 jest prawid³owy
switch (Type)
{//to siê wykonuje równie¿ sk³adu jad¹cego bez obs³ugi
case tp_GetValues:
return n?Params[9].asMemCell->Value1():Params[9].asMemCell->Value2();
case tp_PutValues:
return Params[2-n].asdouble;
}
return 0.0; //inne eventy siê nie licz¹
};
vector3 __fastcall TEvent::PositionGet()
{//pobranie wspó³rzêdnych eventu
switch (Type)
{//
case tp_GetValues:
return Params[9].asMemCell->Position(); //wspó³rzêdne pod³¹czonej komórki pamiêci
case tp_PutValues:
return vector3(Params[3].asdouble,Params[4].asdouble,Params[5].asdouble);
}
return vector3(0,0,0); //inne eventy siê nie licz¹
};
bool __fastcall TEvent::StopCommand()
{//
if (Type==tp_GetValues)
return Params[9].asMemCell->StopCommand(); //info o komendzie z komórki
return false;
};
void __fastcall TEvent::StopCommandSent()
{
if (Type==tp_GetValues)
Params[9].asMemCell->StopCommandSent(); //komenda z komórki zosta³a wys³ana
};
void __fastcall TEvent::Append(TEvent *e)
{//doczepienie kolejnych z t¹ sam¹ nazw¹
if (evJoined)
evJoined->Append(e); //rekurencja! - góra kilkanaœcie eventów bêdzie potrzebne
else
{evJoined=e;
e->bEnabled=true; //ten doczepiony mo¿e byæ tylko kolejkowany
}
};

91
Event.h Normal file
View File

@@ -0,0 +1,91 @@
//---------------------------------------------------------------------------
#ifndef EventH
#define EventH
#include "Classes.h"
#include "dumb3d.h"
using namespace Math3D;
typedef enum { tp_Unknown, tp_Sound, tp_SoundPos, tp_Exit,
tp_Disable, tp_Velocity, tp_Animation, tp_Lights,
tp_UpdateValues, tp_GetValues, tp_PutValues,
tp_Switch, tp_DynVel, tp_TrackVel, tp_Multiple,
tp_AddValues, tp_Ignored, tp_CopyValues, tp_WhoIs,
tp_LogValues, tp_Visible,
tp_Voltage, tp_Message, tp_Friction
} TEventType;
const int update_memstring =0x0000001; //zmodyfikowaæ tekst (UpdateValues)
const int update_memval1 =0x0000002; //zmodyfikowaæ pierwsz¹ wartosæ
const int update_memval2 =0x0000004; //zmodyfikowaæ drug¹ wartosæ
const int update_memadd =0x0000008; //dodaæ do poprzedniej zawartoœci
const int update_load =0x0000010; //odczytaæ ³adunek
const int update_only =0x00000FF; //wartoϾ graniczna
const int conditional_memstring =0x0000100; //porównanie tekstu
const int conditional_memval1 =0x0000200; //porównanie pierwszej wartoœci liczbowej
const int conditional_memval2 =0x0000400; //porównanie drugiej wartoœci
const int conditional_else =0x0010000; //flaga odwrócenia warunku (przesuwana bitowo)
const int conditional_anyelse =0x0FF0000; //do sprawdzania, czy s¹ odwrócone warunki
const int conditional_trackoccupied =0x1000000; //jeœli tor zajêty
const int conditional_trackfree =0x2000000; //jeœli tor wolny
const int conditional_propability =0x4000000; //zale¿nie od generatora lizcb losowych
const int conditional_memcompare =0x8000000; //porównanie zawartoœci
union TParam
{
void *asPointer;
TMemCell *asMemCell;
TGroundNode *nGroundNode;
TTrack *asTrack;
TAnimModel *asModel;
TAnimContainer *asAnimContainer;
TTrain *asTrain;
TDynamicObject *asDynamic;
TEvent *asEvent;
bool asBool;
double asdouble;
int asInt;
TTextSound *tsTextSound;
char *asText;
TCommandType asCommand;
TTractionPowerSource *psPower;
};
class TEvent //zmienne: ev*
{//zdarzenie
private:
void __fastcall Conditions(cParser* parser,AnsiString s);
public:
AnsiString asName;
bool bEnabled; //false gdy ma nie byæ dodawany do kolejki (skanowanie sygna³ów)
int iQueued; //ile razy dodany do kolejki
//bool bIsHistory;
TEvent *evNext; //nastêpny w kolejce
TEvent *evNext2;
TEventType Type;
double fStartTime;
double fDelay;
TDynamicObject *Activator;
TParam Params[13]; //McZapkie-070502 //Ra: zamieniæ to na union/struct
unsigned int iFlags; //zamiast Params[8] z flagami warunku
AnsiString asNodeName; //McZapkie-100302 - dodalem zeby zapamietac nazwe toru
TEvent *evJoined; //kolejny event z t¹ sam¹ nazw¹ - od wersji 378
double fRandomDelay; //zakres dodatkowego opóŸnienia
public: //metody
__fastcall TEvent(AnsiString m="");
__fastcall ~TEvent();
void __fastcall Init();
void __fastcall Load(cParser* parser,vector3 *org);
void __fastcall AddToQuery(TEvent *e);
AnsiString __fastcall CommandGet();
TCommandType __fastcall Command();
double __fastcall ValueGet(int n);
vector3 __fastcall PositionGet();
bool __fastcall StopCommand();
void __fastcall StopCommandSent();
void __fastcall Append(TEvent *e);
};
//---------------------------------------------------------------------------
#endif

105
FadeSound.cpp Normal file
View File

@@ -0,0 +1,105 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Timer.h"
#include "FadeSound.h"
__fastcall TFadeSound::TFadeSound()
{
Sound= NULL;
fFade= 0;
dt= 0;
fTime= 0;
}
__fastcall TFadeSound::~TFadeSound()
{
Free();
}
void __fastcall TFadeSound::Free()
{
}
void __fastcall TFadeSound::Init(char *Name, float fNewFade)
{
Sound= TSoundsManager::GetFromName(Name,false);
if (Sound)
Sound->SetVolume(0);
fFade= fNewFade;
fTime= 0;
}
void __fastcall TFadeSound::TurnOn()
{
State= ss_Starting;
Sound->Play(0,0,DSBPLAY_LOOPING);
fTime= fFade;
}
void __fastcall TFadeSound::TurnOff()
{
State= ss_ShuttingDown;
}
void __fastcall TFadeSound::Update()
{
if (State==ss_Starting)
{
fTime+= Timer::GetDeltaTime();
// SoundStart->SetVolume(-1000*(4-fTime)/4);
if (fTime>=fFade)
{
fTime= fFade;
State= ss_Commencing;
Sound->SetVolume(-2000*(fFade-fTime)/fFade);
Sound->SetFrequency(44100-500+500*(fTime)/fFade);
}
else
if (Timer::GetSoundTimer())
{
Sound->SetVolume(-2000*(fFade-fTime)/fFade);
Sound->SetFrequency(44100-500+500*(fTime)/fFade);
}
}
else
if (State==ss_ShuttingDown)
{
fTime-= Timer::GetDeltaTime();
if (fTime<=0)
{
State= ss_Off;
fTime= 0;
Sound->Stop();
}
if (Timer::GetSoundTimer())
{ //DSBVOLUME_MIN
Sound->SetVolume(-2000*(fFade-fTime)/fFade);
Sound->SetFrequency(44100-500+500*fTime/fFade);
}
}
}
void __fastcall TFadeSound::Volume(long vol)
{
float glos= 1;
Sound->SetVolume(vol*glos);
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

29
FadeSound.h Normal file
View File

@@ -0,0 +1,29 @@
//---------------------------------------------------------------------------
#ifndef FadeSoundH
#define FadeSoundH
#include "Sound.h"
#include "AdvSound.h"
class TFadeSound
{
PSound Sound;
float fFade;
float dt,fTime;
TSoundState State;
public:
__fastcall TFadeSound();
__fastcall ~TFadeSound();
void __fastcall Init(char *Name, float fNewFade);
void __fastcall TurnOn();
void __fastcall TurnOff();
bool __fastcall Playing() {return (State==ss_Commencing || State==ss_Starting); };
void __fastcall Free();
void __fastcall Update();
void __fastcall Volume(long vol);
};
//---------------------------------------------------------------------------
#endif

27
Float3d.cpp Normal file
View File

@@ -0,0 +1,27 @@
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "float3d.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
void __fastcall float4x4::Quaternion(float4 *q)
{//konwersja kwaternionu obrotu na macierz obrotu
float xx=q->x*q->x,yy=q->y*q->y,zz=q->z*q->z;
float xy=q->x*q->y,xz=q->x*q->z,yz=q->y*q->z;
float wx=q->w*q->x,wy=q->w*q->y,wz=q->w*q->z;
e[ 0]=1.0f-yy-yy-zz-zz;
e[ 1]=xy+xy+wz+wz;
e[ 2]=xz+xz-wy-wy;
e[ 4]=xy+xy-wz-wz;
e[ 5]=1.0f-xx-xx-zz-zz;
e[ 6]=yz+yz+wx+wx;
e[ 8]=xz+xz+wy+wy;
e[ 9]=yz+yz-wx-wx;
e[10]=1.0f-xx-xx-yy-yy;
//czwartej kolumny i czwartego wiersza nie ruszamy
};

269
Float3d.h Normal file
View File

@@ -0,0 +1,269 @@
//---------------------------------------------------------------------------
#ifndef float3dH
#define float3dH
#include <math.h>
//---------------------------------------------------------------------------
class float3
{//wapó³rzêdne wiercho³ka 3D o pojedynczej precyzji
public:
float x,y,z;
float3(void) {};
__fastcall float3(float a,float b,float c) {x=a;y=b;z=c;};
double inline __fastcall Length() const;
};
inline bool operator==(const float3& v1,const float3& v2)
{return (v1.x==v2.x&&v1.y==v2.y&&v1.z==v2.z);
};
inline float3& operator+=(float3& v1,const float3& v2)
{v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z;
return v1;
};
inline float3 operator-(const float3& v)
{return float3(-v.x,-v.y,-v.z);
};
inline float3 operator-(const float3 &v1,const float3 &v2)
{return float3(v1.x-v2.x,v1.y-v2.y,v1.z-v2.z);
};
inline float3 operator+(const float3 &v1,const float3 &v2)
{return float3(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z);
};
double inline __fastcall float3::Length() const
{return sqrt(x*x+y*y+z*z);
};
inline float3 operator/(const float3& v, double k)
{return float3(v.x/k,v.y/k,v.z/k);
};
inline float3 SafeNormalize(const float3 &v)
{//bezpieczna normalizacja (wektor d³ugoœci 1.0)
double l=v.Length();
float3 retVal;
if (l==0)
retVal.x=retVal.y=retVal.z=0;
else
retVal=v/l;
return retVal;
};
inline float3 CrossProduct(const float3& v1,const float3& v2)
{return float3(v1.y*v2.z-v1.z*v2.y,v2.x*v1.z-v2.z*v1.x,v1.x*v2.y-v1.y*v2.x);
}
class float4
{//kwaternion obrotu
public:
float x,y,z,w;
__fastcall float4() {x=y=z=0.f;w=1.f;};
__fastcall float4(float a,float b,float c,float d) {x=a;y=b;z=c;w=d;};
double inline float4::LengthSquared() const
{return x*x+y*y+z*z+w*w;};
double inline float4::Length() const
{return sqrt(x*x+y*y+z*z+w*w);};
};
inline float4 operator*(const float4 &q1,const float4 &q2)
{//mno¿enie to prawie jak mno¿enie macierzy
return float4
(q1.w*q2.x+q1.x*q2.w+q1.y*q2.z-q1.z*q2.y,
q1.w*q2.y+q1.y*q2.w+q1.z*q2.x-q1.x*q2.z,
q1.w*q2.z+q1.z*q2.w+q1.x*q2.y-q1.y*q2.x,
q1.w*q2.w-q1.x*q2.x-q1.y*q2.y-q1.z*q2.z
);
}
inline float4 operator-(const float4& q)
{//sprzê¿ony; odwrotny tylko dla znormalizowanych!
return float4(-q.x,-q.y,-q.z,q.w);
};
inline float4 operator-(const float4 &q1,const float4 &q2)
{//z odejmowaniem nie ma lekko
return (-q1)*q2; //inwersja tylko dla znormalizowanych!
};
inline float4 operator+(const float4 &v1,const float4 &v2)
{return float4(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z,v1.w+v2.w);};
inline float4 operator/(const float4& v, double k)
{return float4(v.x/k,v.y/k,v.z/k,v.w/k);};
inline float4 Normalize(const float4 &v)
{//bezpieczna normalizacja (wektor d³ugoœci 1.0)
double l=v.LengthSquared();
if (l==1.0)
return v;
if (l==0.0)
return float4(); //wektor zerowy, w=1
else
return v/sqrt(l); //pierwiastek liczony tylko jeœli trzeba wykonaæ dzielenia
};
float Dot(const float4 &q1,const float4 &q2)
{//iloczyn skalarny
return q1.x*q2.x+q1.y*q2.y+q1.z*q2.z+q1.w*q2.w;
}
inline float4& operator*=(float4& v1,double d)
{//mno¿enie przez skalar, jaki ma sens?
v1.x*=d; v1.y*=d; v1.z*=d; v1.w*=d;
return v1;
};
inline float4 Slerp(const float4 &q0,const float4 &q1,float t)
//void Slerp(QUATERNION *Out, const QUATERNION &q0, const QUATERNION &q1, float t)
{//interpolacja sweryczna
float cosOmega=Dot(q0,q1);
float4 new_q1(q1);
if (cosOmega<0.0f)
{//je¿eli s¹ niezgodne kierunki, jeden z nich trzeba zanegowaæ
new_q1.x=-new_q1.x;
new_q1.y=-new_q1.y;
new_q1.z=-new_q1.z;
new_q1.w=-new_q1.w;
cosOmega=-cosOmega;
}
double k0,k1;
if (cosOmega>0.9999f)
{//jeœli jesteœmy z (t) na maksimum kosinusa, to tam prawie liniowo jest
k0=1.0f-t;
k1=t;
}
else
{//a w ogólnym przypadku trzeba liczyæ na trygonometriê
double sinOmega=sqrt(1.0f-cosOmega*cosOmega); //sinus z jedynki tryg.
double omega=atan2(sinOmega,cosOmega); //wyznaczenie k¹ta
double oneOverSinOmega=1.0f/sinOmega; //odwrotnoϾ sinusa, bo sinus w mianowniku
k0=sin((1.0f-t)*omega)*oneOverSinOmega;
k1=sin(t*omega)*oneOverSinOmega;
}
return float4
(q0.x*k0+new_q1.x*k1,
q0.y*k0+new_q1.y*k1,
q0.z*k0+new_q1.z*k1,
q0.w*k0+new_q1.w*k1
);
}
struct float8
{//wiercho³ek 3D z wektorem normalnym i mapowaniem, pojedyncza precyzja
public:
float3 Point;
float3 Normal;
float tu,tv;
};
class float4x4
{//macierz transformacji pojedynczej precyzji
float e[16];
public:
float4x4(void) {};
float4x4(float f[16]) {for (int i=0;i<16;++i) e[i]=f[i];};
float* __fastcall operator() (int i) { return &e[i<<2]; }
const float* __fastcall readArray(void) { return e; }
void __fastcall Identity()
{for (int i=0;i<16;++i)
e[i]=0;
e[0]=e[5]=e[10]=e[15]=1.0f;
}
const float* operator[](int i) const {return &e[i<<2];};
void __fastcall InitialRotate()
{//taka specjalna rotacja, nie ma co ci¹gaæ trygonometrii
float f;
for (int i=0;i<16;i+=4)
{e[i]=-e[i]; //zmiana znaku X
f=e[i+1]; e[i+1]=e[i+2]; e[i+2]=f; //zamiana Y i Z
}
};
inline float4x4& Rotation(double angle,float3 axis);
inline bool IdentityIs()
{//sprawdzenie jednostkowoœci
for (int i=0;i<16;++i)
if (e[i]!=((i%5)?0.0:1.0)) //jedynki tylko na 0, 5, 10 i 15
return false;
return true;
}
void __fastcall Quaternion(float4 *q);
inline float3* TranslationGet()
{return (float3*)(e+12);}
};
inline float3 operator*(const float4x4& m,const float3& v)
{//mno¿enie wektora przez macierz
return float3(
v.x*m[0][0]+v.y*m[1][0]+v.z*m[2][0]+m[3][0],
v.x*m[0][1]+v.y*m[1][1]+v.z*m[2][1]+m[3][1],
v.x*m[0][2]+v.y*m[1][2]+v.z*m[2][2]+m[3][2]
);
}
inline float4x4& float4x4::Rotation(double angle,float3 axis)
{
double c=cos(angle);
double s=sin(angle);
// One minus c (short name for legibility of formulai)
double omc=(1-c);
if (axis.Length()!=1.0f) axis=SafeNormalize(axis);
double x = axis.x;
double y = axis.y;
double z = axis.z;
double xs = x * s;
double ys = y * s;
double zs = z * s;
double xyomc = x * y * omc;
double xzomc = x * z * omc;
double yzomc = y * z * omc;
e[0] =x*x*omc+c;
e[1] =xyomc+zs;
e[2] =xzomc-ys;
e[3] =0;
e[4] =xyomc-zs;
e[5] =y*y*omc+c;
e[6] =yzomc+xs;
e[7] =0;
e[8] =xzomc+ys;
e[9] =yzomc-xs;
e[10]=z*z*omc+c;
e[11]=0;
e[12]=0;
e[13]=0;
e[14]=0;
e[15]=1;
return *this;
};
inline float4x4 operator*(const float4x4& m1, const float4x4& m2)
{//iloczyn macierzy
float4x4 retVal;
for (int x=0;x<4;++x)
for (int y=0;y<4;++y)
{
retVal(x)[y]=0;
for (int i=0;i<4;++i)
retVal(x)[y]+=m1[i][y]*m2[x][i];
}
return retVal;
};
// From code in Graphics Gems; p. 766
inline float Det2x2(float a,float b,float c,float d)
{//obliczenie wyznacznika macierzy 2×2
return a*d-b*c;
};
inline float Det3x3(float a1,float a2,float a3,
float b1,float b2,float b3,
float c1,float c2,float c3)
{//obliczenie wyznacznika macierzy 3×3
return
+a1*Det2x2(b2,b3,c2,c3)
-b1*Det2x2(a2,a3,c2,c3)
+c1*Det2x2(a2,a3,b2,b3);
};
float Det(const float4x4 &m)
{//obliczenie wyznacznika macierzy 4×4
float a1=m[0][0],a2=m[1][0],a3=m[2][0],a4=m[3][0];
float b1=m[0][1],b2=m[1][1],b3=m[2][1],b4=m[3][1];
float c1=m[0][2],c2=m[1][2],c3=m[2][2],c4=m[3][2];
float d1=m[0][3],d2=m[1][3],d3=m[2][3],d4=m[3][3];
return
+a1*Det3x3(b2,b3,b4,c2,c3,c4,d2,d3,d4)
-b1*Det3x3(a2,a3,a4,c2,c3,c4,d2,d3,d4)
+c1*Det3x3(a2,a3,a4,b2,b3,b4,d2,d3,d4)
-d1*Det3x3(a2,a3,a4,b2,b3,b4,c2,c3,c4);
};
#endif

45
Forth.cpp Normal file
View File

@@ -0,0 +1,45 @@
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Forth.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
/* Ra: Forth jest prostym językiem programowania, funkcjonującym na dosyć
niskim poziomie. Może być zarówno interpretowany jak i kompilowany, co
pozwala szybko działać skompilowanym programom, jak również wykonywać
polecenia wprowadzane z klawiatury. Za pomocą zdefiniowanych kompilatorów
można definiować nowe funkcje, można również tworzyć nowe struktury jezyka,
np. wykraczające poza dotychczasową składnię. Prostota i wydajność są okupione
nieco specyficzną składnią, wynikającą z użycia stosu do obliczeń (tzw. odwrotna
notacja polska).
Forth ma być używany jako:
1. Alternatywna postać eventów. Dotychczasowe eventy w sceneriach mogą być
traktowane jako funkcje języka Forth. Jednocześnie można uzyskać uelastycznienie
składni, poprzez np. połączenie w jednym wpisie różnych typów eventów wraz z
dodaniem warunków dostępnych tylko dla Multiple. Również można będzie używać
wyrażeń języka Forth, czyli dokonywać obliczeń.
2. Jako docelowa postać schematów obwodów Ladder Diagram. Można zrobić tak, by
program źródłowy w Forth (przy pewnych ograniczeniach) był wyświetlany graficznie
jako Ladder Diagram. Jednocześnie graficzne modyfikacje schematu można by
przełożyć na postać tekstową Forth i skompilować na kod niskiego poziomu.
3. Jako algorytm funkcjonowania AI, możliwy do zaprogramowania na zewnątzr EXE.
Każdy użytkownik będzie mógł swój własny styl jazdy.
4. Jako algorytm sterowania ruchem (zależności na stacji).
5. Jako AI stacji, zarządzające ruchem na stacji zależnie w czasie rzeczywistym.
Względem pierwotnego języka Forth, użyty tutaj będzie miał pewne odstępstwa:
1. Operacje na liczbach czterobajtowych float. Należy we własnym zakresie dbać
o zgodność użytych funkcji z typem argumentu na stosie.
2. Jedynym typem całkowitym jest czterobajtowy int.
3. Do wyszukiwania obiektów w scenerii po nazwie (torów, eventów), używane jest
drzewo zamiast listy.
Wpisy w scenerii, przetwarzane jako komendy Forth, nie mogą używać średnika jako
separatora słów. Uniemożliwia to używanie średnika jako słowa.
*/

10
Forth.h Normal file
View File

@@ -0,0 +1,10 @@
//---------------------------------------------------------------------------
#ifndef ForthH
#define ForthH
//---------------------------------------------------------------------------
class Forth
{//klasa obs³ugi jêzyka
};
#endif

217
Gauge.cpp Normal file
View File

@@ -0,0 +1,217 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Timer.h"
#include "QueryParserComp.hpp"
#include "Model3d.h"
#include "Gauge.h"
#include "Console.h"
__fastcall TGauge::TGauge()
{
eType=gt_Unknown;
fFriction=0.0;
fDesiredValue=0.0;
fValue=0.0;
fOffset=0.0;
fScale=1.0;
fStepSize=5;
//iChannel=-1; //kana³ analogowej komunikacji zwrotnej
SubModel=NULL;
};
__fastcall TGauge::~TGauge()
{
};
void __fastcall TGauge::Clear()
{
SubModel=NULL;
eType=gt_Unknown;
fValue=0;
fDesiredValue=0;
};
void __fastcall TGauge::Init(TSubModel *NewSubModel,TGaugeType eNewType,double fNewScale,double fNewOffset,double fNewFriction,double fNewValue)
{//ustawienie parametrów animacji submodelu
if (NewSubModel)
{//warunek na wszelki wypadek, gdyby siê submodel nie pod³¹czy³
fFriction=fNewFriction;
fValue=fNewValue;
fOffset=fNewOffset;
fScale=fNewScale;
SubModel=NewSubModel;
eType=eNewType;
if (eType==gt_Digital)
{
TSubModel *sm=SubModel->ChildGet();
do
{//pêtla po submodelach potomnych i obracanie ich o k¹t zale¿y od cyfry w (fValue)
if (sm->pName)
{//musi mieæ niepust¹ nazwê
if ((*sm->pName)>='0')
if ((*sm->pName)<='9')
sm->WillBeAnimated(); //wy³¹czenie optymalizacji
}
sm=sm->NextGet();
} while (sm);
}
else //a banan mo¿e byæ z optymalizacj¹?
NewSubModel->WillBeAnimated(); //wy³¹czenie ignowania jedynkowego transformu
}
};
bool __fastcall TGauge::Load(TQueryParserComp *Parser,TModel3d *md1,TModel3d *md2,double mul)
{
AnsiString str1=Parser->GetNextSymbol();
AnsiString str2=Parser->GetNextSymbol().LowerCase();
double val3=Parser->GetNextSymbol().ToDouble()*mul;
double val4=Parser->GetNextSymbol().ToDouble();
double val5=Parser->GetNextSymbol().ToDouble();
TSubModel *sm=md1->GetFromName(str1.c_str());
if (sm) //jeœli nie znaleziony
md2=NULL; //informacja, ¿e znaleziony
else
if (md2) //a jest podany drugi model (np. zewnêtrzny)
sm=md2->GetFromName(str1.c_str()); //to mo¿e tam bêdzie, co za ró¿nica gdzie
if (str2=="mov")
Init(sm,gt_Move,val3,val4,val5);
else if (str2=="wip")
Init(sm,gt_Wiper,val3,val4,val5);
else if (str2=="dgt")
Init(sm,gt_Digital,val3,val4,val5);
else
Init(sm,gt_Rotate,val3,val4,val5);
return (md2); //true, gdy podany model zewnêtrzny, a w kabinie nie by³o
};
void __fastcall TGauge::PermIncValue(double fNewDesired)
{
fDesiredValue=fDesiredValue+fNewDesired*fScale+fOffset;
if (fDesiredValue-fOffset>360/fScale)
{
fDesiredValue=fDesiredValue-(360/fScale);
fValue=fValue-(360/fScale);
}
};
void __fastcall TGauge::IncValue(double fNewDesired)
{//u¿ywane tylko dla uniwersali
fDesiredValue=fDesiredValue+fNewDesired*fScale+fOffset;
if (fDesiredValue>fScale+fOffset)
fDesiredValue=fScale+fOffset;
};
void __fastcall TGauge::DecValue(double fNewDesired)
{//u¿ywane tylko dla uniwersali
fDesiredValue=fDesiredValue-fNewDesired*fScale+fOffset;
if (fDesiredValue<0) fDesiredValue=0;
};
void __fastcall TGauge::UpdateValue(double fNewDesired)
{//ustawienie wartoœci docelowej
fDesiredValue=fNewDesired*fScale+fOffset;
};
void __fastcall TGauge::PutValue(double fNewDesired)
{//McZapkie-281102: natychmiastowe wpisanie wartosci
fDesiredValue=fNewDesired*fScale+fOffset;
fValue=fDesiredValue;
};
void __fastcall TGauge::Update()
{
float dt=Timer::GetDeltaTime();
if ((fFriction>0)&&(dt<0.5*fFriction)) //McZapkie-281102: zabezpieczenie przed oscylacjami dla dlugich czasow
fValue+=dt*(fDesiredValue-fValue)/fFriction;
else
fValue=fDesiredValue;
if (SubModel)
{//warunek na wszelki wypadek, gdyby siê submodel nie pod³¹czy³
TSubModel *sm;
switch (eType)
{
case gt_Rotate:
SubModel->SetRotate(float3(0,1,0),fValue*360.0);
break;
case gt_Move:
SubModel->SetTranslate(float3(0,0,fValue));
break;
case gt_Wiper:
SubModel->SetRotate(float3(0,1,0),fValue*360.0);
sm=SubModel->ChildGet();
if (sm)
{sm->SetRotate(float3(0,1,0),fValue*360.0);
sm=sm->ChildGet();
if (sm)
sm->SetRotate(float3(0,1,0),fValue*360.0);
}
break;
case gt_Digital: //Ra 2014-07: licznik cyfrowy
sm=SubModel->ChildGet();
AnsiString n=FormatFloat("0000000000",floor(fValue)); //na razie tak trochê bez sensu
do
{//pêtla po submodelach potomnych i obracanie ich o k¹t zale¿y od cyfry w (fValue)
if (sm->pName)
{//musi mieæ niepust¹ nazwê
if ((*sm->pName)>='0')
if ((*sm->pName)<='9')
sm->SetRotate(float3(0,1,0),-36.0*(n['0'+10-(*sm->pName)]-'0'));
}
sm=sm->NextGet();
} while (sm);
break;
}
}
};
void __fastcall TGauge::Render()
{
};
void __fastcall TGauge::AssignFloat(float* fValue)
{
cDataType='f';
fData=fValue;
};
void __fastcall TGauge::AssignDouble(double* dValue)
{
cDataType='d';
dData=dValue;
};
void __fastcall TGauge::AssignInt(int* iValue)
{
cDataType='i';
iData=iValue;
};
void __fastcall TGauge::UpdateValue()
{//ustawienie wartoœci docelowej z parametru
switch (cDataType)
{//to nie jest zbyt optymalne, mo¿na by zrobiæ osobne funkcje
case 'f':
fDesiredValue=(*fData)*fScale+fOffset;
break;
case 'd':
fDesiredValue=(*dData)*fScale+fOffset;
break;
case 'i':
fDesiredValue=(*iData)*fScale+fOffset;
break;
}
};
//---------------------------------------------------------------------------
#pragma package(smart_init)

61
Gauge.h Normal file
View File

@@ -0,0 +1,61 @@
//---------------------------------------------------------------------------
#ifndef GaugeH
#define GaugeH
//#include "Classes.h"
#include "QueryParserComp.hpp"
//class Queryparsercomp::TQueryParserComp;
class TSubModel;
class TModel3d;
typedef enum
{//typ ruchu
gt_Unknown, //na razie nie znany
gt_Rotate, //obrót
gt_Move, //przesuniêcie równoleg³e
gt_Wiper, //obrót trzech kolejnych submodeli o ten sam k¹t (np. wycieraczka, drzwi harmonijkowe)
gt_Digital //licznik cyfrowy, np. kilometrów
} TGaugeType;
class TGauge //zmienne "gg"
{//animowany wskaŸnik, mog¹cy przyjmowaæ wiele stanów poœrednich
private:
TGaugeType eType; //typ ruchu
double fFriction; //hamowanie przy zli¿aniu siê do zadanej wartoœci
double fDesiredValue; //wartoϾ docelowa
double fValue; //wartoϾ obecna
double fOffset; //wartoœæ pocz¹tkowa ("0")
double fScale; //wartoœæ koñcowa ("1")
double fStepSize; //nie u¿ywane
char cDataType; //typ zmiennej parametru: f-float, d-double, i-int
union
{//wskaŸnik na parametr pokazywany przez animacjê
float* fData;
double* dData;
int* iData;
};
public:
__fastcall TGauge();
__fastcall ~TGauge();
void __fastcall Clear();
void __fastcall Init(TSubModel *NewSubModel,TGaugeType eNewTyp,double fNewScale=1,double fNewOffset=0,double fNewFriction=0,double fNewValue=0);
bool __fastcall Load(TQueryParserComp *Parser,TModel3d *md1,TModel3d *md2=NULL,double mul=1.0);
void __fastcall PermIncValue(double fNewDesired);
void __fastcall IncValue(double fNewDesired);
void __fastcall DecValue(double fNewDesired);
void __fastcall UpdateValue(double fNewDesired);
void __fastcall PutValue(double fNewDesired);
float GetValue() {return fValue;};
void __fastcall Update();
void __fastcall Render();
void __fastcall AssignFloat(float* fValue);
void __fastcall AssignDouble(double* dValue);
void __fastcall AssignInt(int* iValue);
void __fastcall UpdateValue();
TSubModel *SubModel; //McZapkie-310302: zeby mozna bylo sprawdzac czy zainicjowany poprawnie
};
//---------------------------------------------------------------------------
#endif

119
Geom.cpp Normal file
View File

@@ -0,0 +1,119 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#include <gl/gl.h>
#include <gl/glu.h>
#include "opengl/glut.h"
#pragma hdrstop
#include "Texture.h"
#include "usefull.h"
#include "Globals.h"
#include "Geom.h"
__fastcall TGeometry::TGeometry()
{
}
__fastcall TGeometry::~TGeometry()
{
}
bool __fastcall TGeometry::Init()
{
}
vector3 __fastcall TGeometry::Load(TQueryParserComp *Parser)
{
str= Parser->GetNextSymbol().LowerCase();
tmp->TextureID= TTexturesManager::GetTextureID(str.c_str());
i=0;
do
{
tf= Parser->GetNextSymbol().ToDouble();
TempVerts[i].Point.x= tf;
tf= Parser->GetNextSymbol().ToDouble();
TempVerts[i].Point.y= tf;
tf= Parser->GetNextSymbol().ToDouble();
TempVerts[i].Point.z= tf;
tf= Parser->GetNextSymbol().ToDouble();
TempVerts[i].Normal.x= tf;
tf= Parser->GetNextSymbol().ToDouble();
TempVerts[i].Normal.y= tf;
tf= Parser->GetNextSymbol().ToDouble();
TempVerts[i].Normal.z= tf;
str= Parser->GetNextSymbol().LowerCase();
if (str=="x")
TempVerts[i].tu= (TempVerts[i].Point.x+Parser->GetNextSymbol().ToDouble())/Parser->GetNextSymbol().ToDouble();
else
if (str=="y")
TempVerts[i].tu= (TempVerts[i].Point.y+Parser->GetNextSymbol().ToDouble())/Parser->GetNextSymbol().ToDouble();
else
if (str=="z")
TempVerts[i].tu= (TempVerts[i].Point.z+Parser->GetNextSymbol().ToDouble())/Parser->GetNextSymbol().ToDouble();
else
TempVerts[i].tu= str.ToDouble();;
str= Parser->GetNextSymbol().LowerCase();
if (str=="x")
TempVerts[i].tv= (TempVerts[i].Point.x+Parser->GetNextSymbol().ToDouble())/Parser->GetNextSymbol().ToDouble();
else
if (str=="y")
TempVerts[i].tv= (TempVerts[i].Point.y+Parser->GetNextSymbol().ToDouble())/Parser->GetNextSymbol().ToDouble();
else
if (str=="z")
TempVerts[i].tv= (TempVerts[i].Point.z+Parser->GetNextSymbol().ToDouble())/Parser->GetNextSymbol().ToDouble();
else
TempVerts[i].tv= str.ToDouble();;
// tf= Parser->GetNextSymbol().ToDouble();
// TempVerts[i].tu= tf;
// tf= Parser->GetNextSymbol().ToDouble();
// TempVerts[i].tv= tf;
TempVerts[i].Point.RotateZ(aRotate.z/180*M_PI);
TempVerts[i].Point.RotateX(aRotate.x/180*M_PI);
TempVerts[i].Point.RotateY(aRotate.y/180*M_PI);
TempVerts[i].Normal.RotateZ(aRotate.z/180*M_PI);
TempVerts[i].Normal.RotateX(aRotate.x/180*M_PI);
TempVerts[i].Normal.RotateY(aRotate.y/180*M_PI);
TempVerts[i].Point+= pOrigin;
tmp->pCenter+= TempVerts[i].Point;
i++;
// }
} while ( Parser->GetNextSymbol().LowerCase()!="endtri" );
nv= i;
tmp->Init(nv);
tmp->pCenter/= (nv>0?nv:1);
// memcpy(tmp->Vertices,TempVerts,nv*sizeof(TGroundVertex));
r= 0;
for (int i=0; i<nv; i++)
{
tmp->Vertices[i]= TempVerts[i];
tf= SquareMagnitude(tmp->Vertices[i].Point-tmp->pCenter);
if (tf>r)
r= tf;
}
// tmp->fSquareRadius= 2000*2000+r;
tmp->fSquareRadius+= r;
}
bool __fastcall TGeometry::Render()
{
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

38
Geom.h Normal file
View File

@@ -0,0 +1,38 @@
//---------------------------------------------------------------------------
#ifndef GeomH
#define GeomH
#include <gl/gl.h>
#include "QueryParserComp.hpp"
struct TGeomVertex
{
vector3 Point;
vector3 Normal;
double tu,tv;
};
class TGeometry
{
private:
GLuint iType;
union
{
int iNumVerts;
int iNumPts;
};
GLuint TextureID;
TMaterialColor Ambient;
TMaterialColor Diffuse;
TMaterialColor Specular;
public:
__fastcall TGeometry();
__fastcall ~TGeometry();
bool __fastcall Init();
vector3 __fastcall Load(TQueryParserComp *Parser);
bool __fastcall Render();
};
//---------------------------------------------------------------------------
#endif

778
Globals.cpp Normal file
View File

@@ -0,0 +1,778 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
*/
#include "system.hpp"
#pragma hdrstop
#include "Globals.h"
#include "QueryParserComp.hpp"
#include "usefull.h"
#include "Mover.h"
#include "Driver.h"
#include "Console.h"
#include <Controls.hpp> //do odczytu daty
#include "World.h"
//namespace Global {
//parametry do użytku wewnętrznego
//double Global::tSinceStart=0;
TGround *Global::pGround=NULL;
//char Global::CreatorName1[30]="2001-2004 Maciej Czapkiewicz <McZapkie>";
//char Global::CreatorName2[30]="2001-2003 Marcin Woźniak <Marcin_EU>";
//char Global::CreatorName3[20]="2004-2005 Adam Bugiel <ABu>";
//char Global::CreatorName4[30]="2004 Arkadiusz Ślusarczyk <Winger>";
//char Global::CreatorName5[30]="2003-2009 Łukasz Kirchner <Nbmx>";
AnsiString Global::asCurrentSceneryPath="scenery/";
AnsiString Global::asCurrentTexturePath=AnsiString(szTexturePath);
AnsiString Global::asCurrentDynamicPath="";
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
bool Global::detonatoryOK; //info o nowych detonatorach
double Global::ABuDebug=0;
AnsiString Global::asSky="1";
double Global::fOpenGL=0.0; //wersja OpenGL - do sprawdzania obecności rozszerzeń
bool Global::bOpenGL_1_5=false; //czy są dostępne funkcje OpenGL 1.5
double Global::fLuminance=1.0; //jasność światła do automatycznego zapalania
int Global::iReCompile=0; //zwiększany, gdy trzeba odświeżyć siatki
HWND Global::hWnd=NULL; //uchwyt okna
int Global::iCameraLast=-1;
AnsiString Global::asRelease="15.3.1166.469";
AnsiString Global::asVersion="Compilation 2015-03-25, release "+Global::asRelease+"."; //tutaj, bo wysyłany
int Global::iViewMode=0; //co aktualnie widać: 0-kabina, 1-latanie, 2-sprzęgi, 3-dokumenty
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
double Global::fTimeAngleDeg=0.0; //godzina w postaci kąta
float Global::fClockAngleDeg[6]; //kąty obrotu cylindrów dla zegara cyfrowego
char* Global::szTexturesTGA[4]={"tga","dds","tex","bmp"}; //lista tekstur od TGA
char* Global::szTexturesDDS[4]={"dds","tga","tex","bmp"}; //lista tekstur od DDS
int Global::iKeyLast=0; //ostatnio naciśnięty klawisz w celu logowania
GLuint Global::iTextureId=0; //ostatnio użyta tekstura 2D
int Global::iPause=0x10; //globalna pauza ruchu
bool Global::bActive=true; //czy jest aktywnym oknem
int Global::iErorrCounter=0; //licznik sprawdzań do śledzenia błędów OpenGL
int Global::iTextures=0; //licznik użytych tekstur
TWorld* Global::pWorld=NULL;
Queryparsercomp::TQueryParserComp *Global::qParser=NULL;
cParser *Global::pParser=NULL;
int Global::iSegmentsRendered=90; //ilość segmentów do regulacji wydajności
TCamera* Global::pCamera=NULL; //parametry kamery
TDynamicObject *Global::pUserDynamic=NULL; //pojazd użytkownika, renderowany bez trzęsienia
bool Global::bSmudge=false; //czy wyświetlać smugę, a pojazd użytkownika na końcu
AnsiString Global::asTranscript[5]; //napisy na ekranie (widoczne)
TTranscripts Global::tranTexts; //obiekt obsługujący stenogramy dźwięków na ekranie
//parametry scenerii
vector3 Global::pCameraPosition;
double Global::pCameraRotation;
double Global::pCameraRotationDeg;
vector3 Global::pFreeCameraInit[10];
vector3 Global::pFreeCameraInitAngle[10];
double Global::fFogStart=1700;
double Global::fFogEnd=2000;
GLfloat Global::AtmoColor[]={0.423f,0.702f,1.0f};
GLfloat Global::FogColor[]={0.6f,0.7f,0.8f};
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};
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
GLfloat Global::lightPos[4];
bool Global::bRollFix=true; //czy wykonać przeliczanie przechyłki
bool Global::bJoinEvents=false; //czy grupować eventy o tych samych nazwach
int Global::iHiddenEvents=0; //czy łączyć eventy z torami poprzez nazwę toru
//parametry użytkowe (jak komu pasuje)
int Global::Keys[MaxKeys];
int Global::iWindowWidth=800;
int Global::iWindowHeight=600;
float Global::fDistanceFactor=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::bFreeFly=false;
bool Global::bFullScreen=false;
bool Global::bInactivePause=true; //automatyczna pauza, gdy okno nieaktywne
float Global::fMouseXScale=1.5;
float Global::fMouseYScale=0.2;
char Global::szSceneryFile[256]="td.scn";
AnsiString Global::asHumanCtrlVehicle="EU07-424";
int Global::iMultiplayer=0; //blokada działania niektórych funkcji na rzecz komunikacji
double Global::fMoveLight=-1; //ruchome światło
double Global::fLatitudeDeg=52.0; //szerokość geograficzna
float Global::fFriction=1.0; //mnożnik tarcia - KURS90
double Global::fBrakeStep=1.0; //krok zmiany hamulca dla klawiszy [Num3] i [Num9]
AnsiString Global::asLang="pl"; //domyślny język - http://tools.ietf.org/html/bcp47
//parametry wydajnościowe (np. regulacja FPS, szybkość wczytywania)
bool Global::bAdjustScreenFreq=true;
bool Global::bEnableTraction=true;
bool Global::bLoadTraction=true;
bool Global::bLiveTraction=true;
int Global::iDefaultFiltering=9; //domyślne rozmywanie tekstur TGA bez alfa
int Global::iBallastFiltering=9; //domyślne rozmywanie tekstur podsypki
int Global::iRailProFiltering=5; //domyślne rozmywanie tekstur szyn
int Global::iDynamicFiltering=5; //domyślne rozmywanie tekstur pojazdów
bool Global::bUseVBO=false; //czy jest VBO w karcie graficznej (czy użyć)
GLint Global::iMaxTextureSize=16384; //maksymalny rozmiar tekstury
bool Global::bSmoothTraction=false; //wygładzanie drutów starym sposobem
char** Global::szDefaultExt=Global::szTexturesDDS; //domyślnie od DDS
int Global::iMultisampling=2; //tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
bool Global::bGlutFont=false; //czy tekst generowany przez GLUT32.DLL
int Global::iConvertModels=7; //tworzenie plików binarnych, +2-optymalizacja transformów
int Global::iSlowMotionMask=-1; //maska wyłączanych właściwości dla zwiększenia FPS
int Global::iModifyTGA=7; //czy korygować pliki TGA dla szybszego wczytywania
//bool Global::bTerrainCompact=true; //czy zapisać teren w pliku
TAnimModel *Global::pTerrainCompact=NULL; //do zapisania terenu w pliku
AnsiString Global::asTerrainModel=""; //nazwa obiektu terenu do zapisania w pliku
double Global::fFpsAverage=20.0; //oczekiwana wartosć FPS
double Global::fFpsDeviation=5.0; //odchylenie standardowe FPS
double Global::fFpsMin=0.0; //dolna granica FPS, przy której promień scenerii będzie zmniejszany
double Global::fFpsMax=0.0; //górna granica FPS, przy której promień scenerii będzie zwiększany
double Global::fFpsRadiusMax=3000.0; //maksymalny promień renderowania
int Global::iFpsRadiusMax=225; //maksymalny promień renderowania
double Global::fRadiusFactor=1.1; //współczynnik jednorazowej zmiany promienia scenerii
//parametry testowe (do testowania scenerii i obiektów)
bool Global::bWireFrame=false;
bool Global::bSoundEnabled=true;
int Global::iWriteLogEnabled=3; //maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów
bool Global::bManageNodes=true;
bool Global::bDecompressDDS=false; //czy programowa dekompresja DDS
//parametry do kalibracji
//kolejno współczynniki dla potęg 0, 1, 2, 3 wartości odczytanej z urządzenia
double Global::fCalibrateIn[6][4]={{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}};
double Global::fCalibrateOut[7][4]={{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}};
//parametry przejściowe (do usunięcia)
//bool Global::bTimeChange=false; //Ra: ZiomalCl wyłączył starą wersję nocy
//bool Global::bRenderAlpha=true; //Ra: wywaliłam tę flagę
bool Global::bnewAirCouplers=true;
bool Global::bDoubleAmbient=false; //podwójna jasność ambient
double Global::fTimeSpeed=1.0; //przyspieszenie czasu, zmienna do testów
bool Global::bHideConsole=false; //hunter-271211: ukrywanie konsoli
int Global::iBpp=32; //chyba już nie używa się kart, na których 16bpp coś poprawi
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
AnsiString __fastcall Global::GetNextSymbol()
{//pobranie tokenu z aktualnego parsera
if (qParser) return qParser->EndOfFile?AnsiString("endconfig"):qParser->GetNextSymbol();
if (pParser)
{std::string token;
pParser->getTokens();
*pParser >> token;
return AnsiString(token.c_str());
};
return "";
};
void __fastcall Global::LoadIniFile(AnsiString asFileName)
{
int i;
for (i=0;i<10;++i)
{//zerowanie pozycji kamer
pFreeCameraInit[i]=vector3(0,0,0); //współrzędne w scenerii
pFreeCameraInitAngle[i]=vector3(0,0,0); //kąty obrotu w radianach
}
TFileStream *fs;
fs=new TFileStream(asFileName,fmOpenRead|fmShareCompat);
if (!fs) return;
AnsiString str="";
int size=fs->Size;
str.SetLength(size);
fs->Read(str.c_str(),size);
//str+="";
delete fs;
TQueryParserComp *Parser;
Parser=new TQueryParserComp(NULL);
Parser->TextToParse=str;
//Parser->LoadStringToParse(asFile);
Parser->First();
ConfigParse(Parser);
delete Parser; //Ra: tego jak zwykle nie było wcześniej :]
};
void __fastcall Global::ConfigParse(TQueryParserComp *qp,cParser *cp)
{//Ra: trzeba by przerobić na cParser, żeby to działało w scenerii
pParser=cp;
qParser=qp;
AnsiString str;
int i;
do
{
str=GetNextSymbol().LowerCase();
if (str==AnsiString("sceneryfile"))
{
str=GetNextSymbol().LowerCase();
strcpy(szSceneryFile,str.c_str());
}
else
if (str==AnsiString("humanctrlvehicle"))
{
str=GetNextSymbol().LowerCase();
asHumanCtrlVehicle=str;
}
else if (str==AnsiString("width"))
iWindowWidth=GetNextSymbol().ToInt();
else if (str==AnsiString("height"))
iWindowHeight=GetNextSymbol().ToInt();
else if (str==AnsiString("heightbase"))
fDistanceFactor=GetNextSymbol().ToInt();
else if (str==AnsiString("bpp"))
iBpp=((GetNextSymbol().LowerCase()==AnsiString("32")) ? 32 : 16 );
else if (str==AnsiString("fullscreen"))
bFullScreen=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("freefly")) //Mczapkie-130302
{
bFreeFly=(GetNextSymbol().LowerCase()==AnsiString("yes"));
pFreeCameraInit[0].x=GetNextSymbol().ToDouble();
pFreeCameraInit[0].y=GetNextSymbol().ToDouble();
pFreeCameraInit[0].z=GetNextSymbol().ToDouble();
}
else if (str==AnsiString("wireframe"))
bWireFrame=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("debugmode")) //McZapkie! - DebugModeFlag uzywana w mover.pas, warto tez blokowac cheaty gdy false
DebugModeFlag=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("soundenabled")) //McZapkie-040302 - blokada dzwieku - przyda sie do debugowania oraz na komp. bez karty dzw.
bSoundEnabled=(GetNextSymbol().LowerCase()==AnsiString("yes"));
//else if (str==AnsiString("renderalpha")) //McZapkie-1312302 - dwuprzebiegowe renderowanie
// bRenderAlpha=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("physicslog")) //McZapkie-030402 - logowanie parametrow fizycznych dla kazdego pojazdu z maszynista
WriteLogFlag=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("physicsdeactivation")) //McZapkie-291103 - usypianie fizyki
PhysicActivationFlag=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("debuglog"))
{//McZapkie-300402 - wylaczanie log.txt
str=GetNextSymbol().LowerCase();
if (str=="yes") iWriteLogEnabled=3;
else if (str=="no") iWriteLogEnabled=0;
else iWriteLogEnabled=str.ToIntDef(3);
}
else if (str==AnsiString("adjustscreenfreq"))
{//McZapkie-240403 - czestotliwosc odswiezania ekranu
str=GetNextSymbol();
bAdjustScreenFreq=(str.LowerCase()==AnsiString("yes"));
}
else if (str==AnsiString("mousescale"))
{//McZapkie-060503 - czulosc ruchu myszy (krecenia glowa)
str=GetNextSymbol();
fMouseXScale=str.ToDouble();
str=GetNextSymbol();
fMouseYScale=str.ToDouble();
}
else if (str==AnsiString("enabletraction"))
{//Winger 040204 - 'zywe' patyki dostosowujace sie do trakcji; Ra 2014-03: teraz łamanie
bEnableTraction=(GetNextSymbol().LowerCase()==AnsiString("yes"));
}
else if (str==AnsiString("loadtraction"))
{//Winger 140404 - ladowanie sie trakcji
bLoadTraction=(GetNextSymbol().LowerCase()==AnsiString("yes"));
}
else if (str==AnsiString("friction")) //mnożnik tarcia - KURS90
fFriction=GetNextSymbol().ToDouble();
else if (str==AnsiString("livetraction"))
{//Winger 160404 - zaleznosc napiecia loka od trakcji; Ra 2014-03: teraz prąd przy braku sieci
bLiveTraction=(GetNextSymbol().LowerCase()==AnsiString("yes"));
}
else if (str==AnsiString("skyenabled"))
{//youBy - niebo
if (GetNextSymbol().LowerCase()==AnsiString("yes"))
asSky="1"; else asSky="0";
}
else if (str==AnsiString("managenodes"))
{
bManageNodes=(GetNextSymbol().LowerCase()==AnsiString("yes"));
}
else if (str==AnsiString("decompressdds"))
{
bDecompressDDS=(GetNextSymbol().LowerCase()==AnsiString("yes"));
}
// ShaXbee - domyslne rozszerzenie tekstur
else if (str==AnsiString("defaultext"))
{str=GetNextSymbol().LowerCase(); //rozszerzenie
if (str=="tga")
szDefaultExt=szTexturesTGA; //domyślnie od TGA
//szDefaultExt=std::string(Parser->GetNextSymbol().LowerCase().c_str());
}
else if (str==AnsiString("newaircouplers"))
bnewAirCouplers=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("defaultfiltering"))
iDefaultFiltering=GetNextSymbol().ToIntDef(-1);
else if (str==AnsiString("ballastfiltering"))
iBallastFiltering=GetNextSymbol().ToIntDef(-1);
else if (str==AnsiString("railprofiltering"))
iRailProFiltering=GetNextSymbol().ToIntDef(-1);
else if (str==AnsiString("dynamicfiltering"))
iDynamicFiltering=GetNextSymbol().ToIntDef(-1);
else if (str==AnsiString("usevbo"))
bUseVBO=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("feedbackmode"))
iFeedbackMode=GetNextSymbol().ToIntDef(1); //domyślnie 1
else if (str==AnsiString("feedbackport"))
iFeedbackPort=GetNextSymbol().ToIntDef(0); //domyślnie 0
else if (str==AnsiString("multiplayer"))
iMultiplayer=GetNextSymbol().ToIntDef(0); //domyślnie 0
else if (str==AnsiString("maxtexturesize"))
{//wymuszenie przeskalowania tekstur
i=GetNextSymbol().ToIntDef(16384); //domyślnie duże
if (i<= 64) iMaxTextureSize= 64; else
if (i<= 128) iMaxTextureSize= 128; else
if (i<= 256) iMaxTextureSize= 256; else
if (i<= 512) iMaxTextureSize= 512; else
if (i<=1024) iMaxTextureSize=1024; else
if (i<=2048) iMaxTextureSize=2048; else
if (i<=4096) iMaxTextureSize=4096; else
if (i<=8192) iMaxTextureSize=8192; else
iMaxTextureSize=16384;
}
else if (str==AnsiString("doubleambient")) //podwójna jasność ambient
bDoubleAmbient=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("movelight")) //numer dnia w roku albo -1
{fMoveLight=GetNextSymbol().ToIntDef(-1); //numer dnia 1..365
if (fMoveLight==0.0)
{//pobranie daty z systemu
unsigned short y,m,d;
TDate date=Now();
date.DecodeDate(&y,&m,&d);
fMoveLight=(double)date-(double)TDate(y,1,1)+1; //numer bieżącego dnia w roku
}
if (fMoveLight>0.0) //tu jest nadal zwiększone o 1
{//obliczenie deklinacji wg:
//http://naturalfrequency.com/Tregenza_Sharples/Daylight_Algorithms/algorithm_1_11.htm
//Spencer J W Fourier series representation of the position of the sun Search 2 (5) 172 (1971)
fMoveLight=M_PI/182.5*(Global::fMoveLight-1.0); //numer dnia w postaci kąta
fSunDeclination=0.006918-0.3999120*cos( fMoveLight)+0.0702570*sin( fMoveLight)
-0.0067580*cos(2*fMoveLight)+0.0009070*sin(2*fMoveLight)
-0.0026970*cos(3*fMoveLight)+0.0014800*sin(3*fMoveLight);
}
}
else if (str==AnsiString("smoothtraction")) //podwójna jasność ambient
bSmoothTraction=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("timespeed")) //przyspieszenie czasu, zmienna do testów
fTimeSpeed=GetNextSymbol().ToIntDef(1);
else if (str==AnsiString("multisampling")) //tryb antyaliasingu: 0=brak,1=2px,2=4px
iMultisampling=GetNextSymbol().ToIntDef(2); //domyślnie 2
else if (str==AnsiString("glutfont")) //tekst generowany przez GLUT
bGlutFont=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("latitude")) //szerokość geograficzna
fLatitudeDeg=GetNextSymbol().ToDouble();
else if (str==AnsiString("convertmodels")) //tworzenie plików binarnych
iConvertModels=GetNextSymbol().ToIntDef(7); //domyślnie 7
else if (str==AnsiString("inactivepause")) //automatyczna pauza, gdy okno nieaktywne
bInactivePause=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("slowmotion")) //tworzenie plików binarnych
iSlowMotionMask=GetNextSymbol().ToIntDef(-1); //domyślnie -1
else if (str==AnsiString("modifytga")) //czy korygować pliki TGA dla szybszego wczytywania
iModifyTGA=GetNextSymbol().ToIntDef(0); //domyślnie 0
else if (str==AnsiString("hideconsole")) //hunter-271211: ukrywanie konsoli
bHideConsole=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("rollfix")) //Ra: poprawianie przechyłki, aby wewnętrzna szyna była "pozioma"
bRollFix=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("fpsaverage")) //oczekiwana wartosć FPS
fFpsAverage=GetNextSymbol().ToDouble();
else if (str==AnsiString("fpsdeviation")) //odchylenie standardowe FPS
fFpsDeviation=GetNextSymbol().ToDouble();
else if (str==AnsiString("fpsradiusmax")) //maksymalny promień renderowania
fFpsRadiusMax=GetNextSymbol().ToDouble();
else if (str==AnsiString("calibratein")) //parametry kalibracji wejść
{//
i=GetNextSymbol().ToIntDef(-1); //numer wejścia
if ((i<0)||(i>5)) i=5; //na ostatni, bo i tak trzeba pominąć wartości
fCalibrateIn[i][0]=GetNextSymbol().ToDouble(); //wyraz wolny
fCalibrateIn[i][1]=GetNextSymbol().ToDouble(); //mnożnik
fCalibrateIn[i][2]=GetNextSymbol().ToDouble(); //mnożnik dla kwadratu
fCalibrateIn[i][3]=GetNextSymbol().ToDouble(); //mnożnik dla sześcianu
}
else if (str==AnsiString("calibrateout")) //parametry kalibracji wyjść
{//
i=GetNextSymbol().ToIntDef(-1); //numer wejścia
if ((i<0)||(i>6)) i=6; //na ostatni, bo i tak trzeba pominąć wartości
fCalibrateOut[i][0]=GetNextSymbol().ToDouble(); //wyraz wolny
fCalibrateOut[i][1]=GetNextSymbol().ToDouble(); //mnożnik liniowy
fCalibrateOut[i][2]=GetNextSymbol().ToDouble(); //mnożnik dla kwadratu
fCalibrateOut[i][3]=GetNextSymbol().ToDouble(); //mnożnik dla sześcianu
}
else if (str==AnsiString("brakestep")) //krok zmiany hamulca dla klawiszy [Num3] i [Num9]
fBrakeStep=GetNextSymbol().ToDouble();
else if (str==AnsiString("joinduplicatedevents")) //czy grupować eventy o tych samych nazwach
bJoinEvents=(GetNextSymbol().LowerCase()==AnsiString("yes"));
else if (str==AnsiString("hiddenevents")) //czy łączyć eventy z torami poprzez nazwę toru
iHiddenEvents=GetNextSymbol().ToIntDef(0);
else if (str==AnsiString("pause")) //czy po wczytaniu ma być pauza?
iPause|=(GetNextSymbol().LowerCase()==AnsiString("yes"))?1:0;
else if (str==AnsiString("lang"))
asLang=GetNextSymbol(); //domyślny język - http://tools.ietf.org/html/bcp47
else if (str==AnsiString("opengl")) //deklarowana wersja OpenGL, żeby powstrzymać błędy
fOpenGL=GetNextSymbol().ToDouble(); //wymuszenie wersji OpenGL
}
while (str!="endconfig"); //(!Parser->EndOfFile)
//na koniec trochę zależności
if (!bLoadTraction) //wczytywanie drutów i słupów
{//tutaj wyłączenie, bo mogą nie być zdefiniowane w INI
bEnableTraction=false; //false = pantograf się nie połamie
bLiveTraction=false; //false = pantografy zawsze zbierają 95% MaxVoltage
}
//if (fMoveLight>0) bDoubleAmbient=false; //wtedy tylko jedno światło ruchome
//if (fOpenGL<1.3) iMultisampling=0; //można by z góry wyłączyć, ale nie mamy jeszcze fOpenGL
if (iMultisampling)
{//antyaliasing całoekranowy wyłącza rozmywanie drutów
bSmoothTraction=false;
}
if (iMultiplayer>0)
{bInactivePause=false; //okno "w tle" nie może pauzować, jeśli włączona komunikacja
//pauzowanie jest zablokowane dla (iMultiplayer&2)>0, więc iMultiplayer=1 da się zapauzować (tryb instruktora)
}
fFpsMin=fFpsAverage-fFpsDeviation; //dolna granica FPS, przy której promień scenerii będzie zmniejszany
fFpsMax=fFpsAverage+fFpsDeviation; //górna granica FPS, przy której promień scenerii będzie zwiększany
if (iPause) iTextMode=VK_F1; //jak pauza, to pokazać zegar
if (qp)
{//to poniżej wykonywane tylko raz, jedynie po wczytaniu eu07.ini
Console::ModeSet(iFeedbackMode,iFeedbackPort); //tryb pracy konsoli sterowniczej
iFpsRadiusMax=0.000025*fFpsRadiusMax*fFpsRadiusMax; //maksymalny promień renderowania 3000.0 -> 225
if (iFpsRadiusMax>400) iFpsRadiusMax=400;
if (fDistanceFactor>1.0)
{//dla 1.0 specjalny tryb bez przeliczania
fDistanceFactor=iWindowHeight/fDistanceFactor; //fDistanceFactor>1.0 dla rozdzielczości większych niż bazowa
fDistanceFactor*=(iMultisampling+1.0)*fDistanceFactor; //do kwadratu, bo większość odległości to ich kwadraty
}
}
}
void __fastcall Global::InitKeys(AnsiString asFileName)
{
// if (FileExists(asFileName))
// {
// Error("Chwilowo plik keys.ini nie jest obsługiwany. Ładuję standardowe ustawienia.\nKeys.ini file is temporarily not functional, loading default keymap...");
/* TQueryParserComp *Parser;
Parser=new TQueryParserComp(NULL);
Parser->LoadStringToParse(asFileName);
for (int keycount=0; keycount<MaxKeys; keycount++)
{
Keys[keycount]=Parser->GetNextSymbol().ToInt();
}
delete Parser;
*/
// }
// else
{
Keys[k_IncMainCtrl]=VK_ADD;
Keys[k_IncMainCtrlFAST]=VK_ADD;
Keys[k_DecMainCtrl]=VK_SUBTRACT;
Keys[k_DecMainCtrlFAST]=VK_SUBTRACT;
Keys[k_IncScndCtrl]=VK_DIVIDE;
Keys[k_IncScndCtrlFAST]=VK_DIVIDE;
Keys[k_DecScndCtrl]=VK_MULTIPLY;
Keys[k_DecScndCtrlFAST]=VK_MULTIPLY;
///*NORMALNE
Keys[k_IncLocalBrakeLevel]=VK_NUMPAD1; //VK_NUMPAD7;
//Keys[k_IncLocalBrakeLevelFAST]=VK_END; //VK_HOME;
Keys[k_DecLocalBrakeLevel]=VK_NUMPAD7; //VK_NUMPAD1;
//Keys[k_DecLocalBrakeLevelFAST]=VK_HOME; //VK_END;
Keys[k_IncBrakeLevel]=VK_NUMPAD3; //VK_NUMPAD9;
Keys[k_DecBrakeLevel]=VK_NUMPAD9; //VK_NUMPAD3;
Keys[k_Releaser]=VK_NUMPAD6;
Keys[k_EmergencyBrake]=VK_NUMPAD0;
Keys[k_Brake3]=VK_NUMPAD8;
Keys[k_Brake2]=VK_NUMPAD5;
Keys[k_Brake1]=VK_NUMPAD2;
Keys[k_Brake0]=VK_NUMPAD4;
Keys[k_WaveBrake]=VK_DECIMAL;
//*/
/*MOJE
Keys[k_IncLocalBrakeLevel]=VK_NUMPAD3; //VK_NUMPAD7;
Keys[k_IncLocalBrakeLevelFAST]=VK_NUMPAD3; //VK_HOME;
Keys[k_DecLocalBrakeLevel]=VK_DECIMAL; //VK_NUMPAD1;
Keys[k_DecLocalBrakeLevelFAST]=VK_DECIMAL; //VK_END;
Keys[k_IncBrakeLevel]=VK_NUMPAD6; //VK_NUMPAD9;
Keys[k_DecBrakeLevel]=VK_NUMPAD9; //VK_NUMPAD3;
Keys[k_Releaser]=VK_NUMPAD5;
Keys[k_EmergencyBrake]=VK_NUMPAD0;
Keys[k_Brake3]=VK_NUMPAD2;
Keys[k_Brake2]=VK_NUMPAD1;
Keys[k_Brake1]=VK_NUMPAD4;
Keys[k_Brake0]=VK_NUMPAD7;
Keys[k_WaveBrake]=VK_NUMPAD8;
*/
Keys[k_AntiSlipping]=VK_RETURN;
Keys[k_Sand]=VkKeyScan('s');
Keys[k_Main]=VkKeyScan('m');
Keys[k_Active]=VkKeyScan('w');
Keys[k_Battery]=VkKeyScan('j');
Keys[k_DirectionForward]=VkKeyScan('d');
Keys[k_DirectionBackward]=VkKeyScan('r');
Keys[k_Fuse]=VkKeyScan('n');
Keys[k_Compressor]=VkKeyScan('c');
Keys[k_Converter]=VkKeyScan('x');
Keys[k_MaxCurrent]=VkKeyScan('f');
Keys[k_CurrentAutoRelay]=VkKeyScan('g');
Keys[k_BrakeProfile]=VkKeyScan('b');
Keys[k_CurrentNext]=VkKeyScan('z');
Keys[k_Czuwak]=VkKeyScan(' ');
Keys[k_Horn]=VkKeyScan('a');
Keys[k_Horn2]=VkKeyScan('a');
Keys[k_FailedEngineCutOff]=VkKeyScan('e');
Keys[k_MechUp]=VK_PRIOR;
Keys[k_MechDown]=VK_NEXT ;
Keys[k_MechLeft]=VK_LEFT ;
Keys[k_MechRight]=VK_RIGHT;
Keys[k_MechForward]=VK_UP;
Keys[k_MechBackward]=VK_DOWN;
Keys[k_CabForward]=VK_HOME;
Keys[k_CabBackward]=VK_END;
Keys[k_Couple]=VK_INSERT;
Keys[k_DeCouple]=VK_DELETE;
Keys[k_ProgramQuit]=VK_F10;
//Keys[k_ProgramPause]=VK_F3;
Keys[k_ProgramHelp]=VK_F1;
//Keys[k_FreeFlyMode]=VK_F4;
Keys[k_WalkMode]=VK_F5;
Keys[k_OpenLeft]=VkKeyScan(',');
Keys[k_OpenRight]=VkKeyScan('.');
Keys[k_CloseLeft]=VkKeyScan(',');
Keys[k_CloseRight]=VkKeyScan('.');
Keys[k_DepartureSignal]=VkKeyScan('/');
//Winger 160204 - obsluga pantografow
Keys[k_PantFrontUp]=VkKeyScan('p'); //Ra: zamieniony przedni z tylnym
Keys[k_PantFrontDown]=VkKeyScan('p');
Keys[k_PantRearUp]=VkKeyScan('o');
Keys[k_PantRearDown]=VkKeyScan('o');
//Winger 020304 - ogrzewanie
Keys[k_Heating]=VkKeyScan('h');
Keys[k_LeftSign]=VkKeyScan('y');
Keys[k_UpperSign]=VkKeyScan('u');
Keys[k_RightSign]=VkKeyScan('i');
Keys[k_EndSign]=VkKeyScan('t');
Keys[k_SmallCompressor]=VkKeyScan('v');
Keys[k_StLinOff]=VkKeyScan('l');
//ABu 090305 - przyciski uniwersalne, do roznych bajerow :)
Keys[k_Univ1]=VkKeyScan('[');
Keys[k_Univ2]=VkKeyScan(']');
Keys[k_Univ3]=VkKeyScan(';');
Keys[k_Univ4]=VkKeyScan('\'');
}
}
/*
vector3 __fastcall Global::GetCameraPosition()
{
return pCameraPosition;
}
*/
void __fastcall Global::SetCameraPosition(vector3 pNewCameraPosition)
{
pCameraPosition=pNewCameraPosition;
}
void __fastcall Global::SetCameraRotation(double Yaw)
{//ustawienie bezwzględnego kierunku kamery z korekcją do przedziału <-M_PI,M_PI>
pCameraRotation=Yaw;
while (pCameraRotation<-M_PI) pCameraRotation+=2*M_PI;
while (pCameraRotation> M_PI) pCameraRotation-=2*M_PI;
pCameraRotationDeg=pCameraRotation*180.0/M_PI;
}
void __fastcall Global::BindTexture(GLuint t)
{//ustawienie aktualnej tekstury, tylko gdy się zmienia
if (t!=iTextureId)
{iTextureId=t;
}
};
void __fastcall Global::TrainDelete(TDynamicObject *d)
{//usunięcie pojazdu prowadzonego przez użytkownika
if (pWorld) pWorld->TrainDelete(d);
};
TDynamicObject* __fastcall Global::DynamicNearest()
{//ustalenie pojazdu najbliższego kamerze
return pGround->DynamicNearest(pCamera->Pos);
};
TDynamicObject* __fastcall Global::CouplerNearest()
{//ustalenie pojazdu najbliższego kamerze
return pGround->CouplerNearest(pCamera->Pos);
};
bool __fastcall Global::AddToQuery(TEvent *event,TDynamicObject *who)
{
return pGround->AddToQuery(event,who);
};
//---------------------------------------------------------------------------
bool __fastcall Global::DoEvents()
{//wywoływać czasem, żeby nie robił wrażenia zawieszonego
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message==WM_QUIT)
return FALSE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return TRUE;
}
//---------------------------------------------------------------------------
__fastcall TTranscripts::TTranscripts()
{
iCount=0; //brak linijek do wyświetlenia
iStart=0; //wypełniać od linijki 0
for (int i=0;i<MAX_TRANSCRIPTS;++i)
{//to do konstruktora można by dać
aLines[i].fHide=-1.0; //wolna pozycja (czas symulacji, 360.0 to doba)
aLines[i].iNext=-1; //nie ma kolejnej
}
fRefreshTime=360.0; //wartośc zaporowa
};
__fastcall TTranscripts::~TTranscripts()
{
};
void __fastcall TTranscripts::AddLine(char *txt,float show,float hide,bool it)
{//dodanie linii do tabeli, (show) i (hide) w [s] od aktualnego czasu
if (show==hide) return; //komentarz jest ignorowany
show=Global::fTimeAngleDeg+show/240.0; //jeśli doba to 360, to 1s będzie równe 1/240
hide=Global::fTimeAngleDeg+hide/240.0;
int i=iStart,j,k; //od czegoś trzeba zacząć
while ((aLines[i].iNext>=0)?(aLines[aLines[i].iNext].fShow<=show):false) //póki nie koniec i wcześniej puszczane
i=aLines[i].iNext; //przejście do kolejnej linijki
//(i) wskazuje na linię, po której należy wstawić dany tekst, chyba że
while (txt?*txt:false)
for (j=0;j<MAX_TRANSCRIPTS;++j)
if (aLines[j].fHide<0.0)
{//znaleziony pierwszy wolny
aLines[j].iNext=aLines[i].iNext; //dotychczasowy następny będzie za nowym
if (aLines[iStart].fHide<0.0) //jeśli tablica jest pusta
iStart=j; //fHide trzeba sprawdzić przed ewentualnym nadpisaniem, gdy i=j=0
else
aLines[i].iNext=j; //a nowy będzie za tamtym wcześniejszym
aLines[j].fShow=show; //wyświetlać od
aLines[j].fHide=hide; //wyświetlać do
aLines[j].bItalic=it;
aLines[j].asText=AnsiString(txt); //bez sensu, wystarczyłby wskaźnik
if ((k=aLines[j].asText.Pos("|"))>0)
{//jak jest podział linijki na wiersze
aLines[j].asText=aLines[j].asText.SubString(1,k-1);
txt+=k;
i=j; //kolejna linijka dopisywana będzie na koniec właśnie dodanej
}
else
txt=NULL; //koniec dodawania
if (fRefreshTime>show) //jeśli odświeżacz ustawiony jest na później
fRefreshTime=show; //to odświeżyć wcześniej
break; //więcej już nic
}
};
void __fastcall TTranscripts::Add(char *txt,float len,bool backgorund)
{//dodanie tekstów, długość dźwięku, czy istotne
if (!txt) return; //pusty tekst
int i=0,j=int(0.5+10.0*len); //[0.1s]
if (*txt=='[')
{//powinny być dwa nawiasy
while (*++txt?*txt!=']':false)
if ((*txt>='0')&&(*txt<='9'))
i=10*i+int(*txt-'0'); //pierwsza liczba aż do ]
if (*txt?*++txt=='[':false)
{j=0; //drugi nawias określa czas zakończenia wyświetlania
while (*++txt?*txt!=']':false)
if ((*txt>='0')&&(*txt<='9'))
j=10*j+int(*txt-'0'); //druga liczba aż do ]
if (*txt) ++txt; //pominięcie drugiego ]
}
}
AddLine(txt,0.1*i,0.1*j,false);
};
void __fastcall TTranscripts::Update()
{//usuwanie niepotrzebnych (nie częściej niż 10 razy na sekundę)
if (fRefreshTime>Global::fTimeAngleDeg)
return; //nie czas jeszcze na zmiany
//czas odświeżenia można ustalić wg tabelki, kiedy coś się w niej zmienia
fRefreshTime=Global::fTimeAngleDeg+360.0; //wartość zaporowa
int i=iStart,j=-1; //od czegoś trzeba zacząć
bool change=false; //czy zmieniać napisy?
do
{
if (aLines[i].fHide>=0.0) //o ile aktywne
if (aLines[i].fHide<Global::fTimeAngleDeg)
{//gdy czas wyświetlania upłynął
aLines[i].fHide=-1.0; //teraz będzie wolną pozycją
if (i==iStart)
iStart=aLines[i].iNext>=0?aLines[i].iNext:0; //przestawienie pierwszego
else if (j>=0)
aLines[j].iNext=aLines[i].iNext; //usunięcie ze środka
change=true;
}
else
{//gdy ma być pokazane
if (aLines[i].fShow>Global::fTimeAngleDeg) //będzie pokazane w przyszłości
if (fRefreshTime>aLines[i].fShow) //a nie ma nic wcześniej
fRefreshTime=aLines[i].fShow;
if (fRefreshTime>aLines[i].fHide)
fRefreshTime=aLines[i].fHide;
}
//można by jeszcze wykrywać, które nowe mają być pokazane
j=i;
i=aLines[i].iNext; //kolejna linijka
} while (i>=0); //póki po tablicy
change=true; //bo na razie nie ma warunku, że coś się dodało
if (change)
{//aktualizacja linijek ekranowych
i=iStart; j=-1;
do
{
if (aLines[i].fHide>0.0) //jeśli nie ukryte
if (aLines[i].fShow<Global::fTimeAngleDeg) //to dodanie linijki do wyświetlania
if (j<5-1) //ograniczona liczba linijek
Global::asTranscript[++j]=aLines[i].asText; //skopiowanie tekstu
i=aLines[i].iNext; //kolejna linijka
} while (i>=0); //póki po tablicy
for (++j;j<5;++j)
Global::asTranscript[j]=""; //i czyszczenie nieużywanych linijek
}
};
//Ra: tymczasowe rozwiązanie kwestii zagranicznych (czeskich) napisów
char bezogonkowo[128]=
"E?,?\"_++?%S<STZZ?`'\"\".--??s>stzz"
" ^^L$A|S^CS<--RZo±,l'uP.,as>L\"lz"
"RAAAALCCCEEEEIIDDNNOOOOxRUUUUYTB"
"raaaalccceeeeiiddnnoooo-ruuuuyt?";
AnsiString __fastcall Global::Bezogonkow(AnsiString str, bool _)
{//wycięcie liter z ogonkami, bo OpenGL nie umie wyświetlić
for (int i=1;i<=str.Length();++i)
if (str[i]&0x80)
str[i]=bezogonkowo[str[i]&0x7F];
else if (str[i]<' ') //znaki sterujące nie są obsługiwane
str[i]=' ';
else if (_) if (str[i]=='_') //nazwy stacji nie mogą zawierać spacji
str[i]=' '; //więc trzeba wyświetlać inaczej
return str;
}
#pragma package(smart_init)

306
Globals.h Normal file
View File

@@ -0,0 +1,306 @@
//---------------------------------------------------------------------------
#ifndef GlobalsH
#define GlobalsH
#include <string>
#include "system.hpp"
#include "opengl/glew.h"
#include "dumb3d.h"
//#include "Classes.h"
using namespace Math3D;
//definicje klawiszy
const int k_IncMainCtrl= 0; //[Num+]
const int k_IncMainCtrlFAST= 1; //[Num+] [Shift]
const int k_DecMainCtrl= 2; //[Num-]
const int k_DecMainCtrlFAST= 3; //[Num-] [Shift]
const int k_IncScndCtrl= 4; //[Num/]
const int k_IncScndCtrlFAST= 5;
const int k_DecScndCtrl= 6;
const int k_DecScndCtrlFAST= 7;
const int k_IncLocalBrakeLevel= 8;
const int k_IncLocalBrakeLevelFAST= 9;
const int k_DecLocalBrakeLevel=10 ;
const int k_DecLocalBrakeLevelFAST= 11;
const int k_IncBrakeLevel= 12;
const int k_DecBrakeLevel= 13;
const int k_Releaser= 14;
const int k_EmergencyBrake= 15;
const int k_Brake3= 16;
const int k_Brake2= 17;
const int k_Brake1= 18;
const int k_Brake0= 19;
const int k_WaveBrake= 20;
const int k_AntiSlipping= 21;
const int k_Sand= 22;
const int k_Main= 23;
const int k_DirectionForward= 24;
const int k_DirectionBackward= 25;
const int k_Fuse= 26;
const int k_Compressor= 27;
const int k_Converter= 28;
const int k_MaxCurrent= 29;
const int k_CurrentAutoRelay= 30;
const int k_BrakeProfile= 31;
const int k_Czuwak= 32;
const int k_Horn= 33;
const int k_Horn2= 34;
const int k_FailedEngineCutOff= 35;
const int k_MechUp= 36;
const int k_MechDown= 37;
const int k_MechLeft= 38;
const int k_MechRight= 39;
const int k_MechForward= 40;
const int k_MechBackward= 41;
const int k_CabForward= 42;
const int k_CabBackward= 43;
const int k_Couple= 44;
const int k_DeCouple= 45;
const int k_ProgramQuit= 46;
//const int k_ProgramPause= 47;
const int k_ProgramHelp= 48;
//NBMX
const int k_OpenLeft= 49;
const int k_OpenRight= 50;
const int k_CloseLeft= 51;
const int k_CloseRight= 52;
const int k_DepartureSignal= 53;
//NBMX
const int k_PantFrontUp= 54;
const int k_PantRearUp= 55;
const int k_PantFrontDown= 56;
const int k_PantRearDown= 57;
const int k_Heating= 58;
//const int k_FreeFlyMode= 59;
const int k_LeftSign = 60;
const int k_UpperSign= 61;
const int k_RightSign= 62;
const int k_SmallCompressor= 63;
const int k_StLinOff= 64;
const int k_CurrentNext=65;
const int k_Univ1=66;
const int k_Univ2=67;
const int k_Univ3=68;
const int k_Univ4=69;
const int k_EndSign=70;
const int k_Active=71;
//Winger 020304
const int k_Battery=72;
const int k_WalkMode=73;
const int MaxKeys= 74;
//klasy dla wskaŸników globalnych
class TGround;
class TWorld;
class TCamera;
class TDynamicObject;
class TAnimModel; //obiekt terenu
namespace Queryparsercomp
{
class TQueryParserComp; //stary(?) parser
}
class cParser; //nowy (powolny!) parser
class TEvent;
class TTextSound;
class TTranscript
{//klasa obs³uguj¹ca linijkê napisu do dŸwiêku
public:
float fShow; //czas pokazania
float fHide; //czas ukrycia/usuniêcia
AnsiString 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
};
#define MAX_TRANSCRIPTS 30
class TTranscripts
{//klasa obs³uguj¹ca napisy do dŸwiêków
TTranscript aLines[MAX_TRANSCRIPTS]; //pozycje na napisy do wyœwietlenia
int iCount; //liczba zajêtych pozycji
int iStart; //pierwsza istotna pozycja w tabeli, ¿eby sortowaæ przestawiaj¹c numerki
float fRefreshTime;
public:
__fastcall TTranscripts();
__fastcall ~TTranscripts();
void __fastcall AddLine(char *txt,float show,float hide,bool it);
void __fastcall Add(char *txt,float len,bool backgorund=false); //dodanie tekstów, d³ugoœæ dŸwiêku, czy istotne
void __fastcall Update(); //usuwanie niepotrzebnych (ok. 10 razy na sekundê)
};
class Global
{
private:
static GLuint iTextureId; //ostatnio u¿yta tekstura 2D
public:
//double Global::tSinceStart;
static int Keys[MaxKeys];
static vector3 pCameraPosition; //pozycja kamery w œwiecie
static double pCameraRotation; //kierunek bezwzglêdny kamery w œwiecie: 0=pó³noc, 90°=zachód (-azymut)
static double pCameraRotationDeg; //w stopniach, dla animacji billboard
static vector3 pFreeCameraInit[10]; //pozycje kamery
static vector3 pFreeCameraInitAngle[10];
static int iWindowWidth;
static int iWindowHeight;
static float fDistanceFactor;
static int iBpp;
static bool bFullScreen;
static bool bFreeFly;
//float RunningTime;
static bool bWireFrame;
static bool bSoundEnabled;
//McZapkie-131202
//static bool bRenderAlpha;
static bool bAdjustScreenFreq;
static bool bEnableTraction;
static bool bLoadTraction;
static float fFriction;
static bool bLiveTraction;
static bool bManageNodes;
static bool bDecompressDDS;
// bool WFreeFly;
static float Global::fMouseXScale;
static float Global::fMouseYScale;
static double fFogStart;
static double fFogEnd;
static TGround *pGround;
static char** szDefaultExt;
static char szSceneryFile[256];
static char CreatorName1[20];
static char CreatorName2[20];
static char CreatorName3[20];
static char CreatorName4[30];
static char CreatorName5[30];
static AnsiString asCurrentSceneryPath;
static AnsiString asCurrentTexturePath;
static AnsiString asCurrentDynamicPath;
//McZapkie-170602: zewnetrzna definicja pojazdu uzytkownika
static AnsiString asHumanCtrlVehicle;
static void __fastcall LoadIniFile(AnsiString asFileName);
static void __fastcall InitKeys(AnsiString asFileName);
inline static vector3 __fastcall GetCameraPosition()
{return pCameraPosition;};
static void __fastcall SetCameraPosition(vector3 pNewCameraPosition);
static void __fastcall SetCameraRotation(double Yaw);
static int iWriteLogEnabled; //maska bitowa: 1-zapis do pliku, 2-okienko
//McZapkie-221002: definicja swiatla dziennego
static GLfloat AtmoColor[];
static GLfloat FogColor[];
//static bool bTimeChange;
static GLfloat ambientDayLight[];
static GLfloat diffuseDayLight[];
static GLfloat specularDayLight[];
static GLfloat ambientLight[];
static GLfloat diffuseLight[];
static GLfloat specularLight[];
static GLfloat whiteLight[];
static GLfloat noLight[];
static GLfloat darkLight[];
static GLfloat lightPos[4];
static int iSlowMotion;
static TDynamicObject *changeDynObj;
static double ABuDebug;
static bool detonatoryOK;
static AnsiString asSky;
static bool bnewAirCouplers;
//Ra: nowe zmienne globalne
static int iDefaultFiltering; //domyœlne rozmywanie tekstur TGA
static int iBallastFiltering; //domyœlne rozmywanie tekstury podsypki
static int iRailProFiltering; //domyœlne rozmywanie tekstury szyn
static int iDynamicFiltering; //domyœlne rozmywanie tekstur pojazdów
static int iReCompile; //zwiêkszany, gdy trzeba odœwie¿yæ siatki
static bool bUseVBO; //czy jest VBO w karcie graficznej
static int iFeedbackMode; //tryb pracy informacji zwrotnej
static int iFeedbackPort; //dodatkowy adres dla informacji zwrotnych
static double fOpenGL; //wersja OpenGL - przyda siê
static bool bOpenGL_1_5; //czy s¹ dostêpne funkcje OpenGL 1.5
static double fLuminance; //jasnoœæ œwiat³a do automatycznego zapalania
static int iMultiplayer; //blokada dzia³ania niektórych eventów na rzecz kominikacji
static HWND hWnd; //uchwyt okna
static int iCameraLast;
static AnsiString asRelease; //numer
static AnsiString asVersion; //z opisem
static int iViewMode; //co aktualnie widaæ: 0-kabina, 1-latanie, 2-sprzêgi, 3-dokumenty, 4-obwody
static GLint iMaxTextureSize; //maksymalny rozmiar tekstury
static int iTextMode; //tryb pracy wyœwietlacza tekstowego
static int iScreenMode[12]; //numer ekranu wyœwietlacza tekstowego
static bool bDoubleAmbient; //podwójna jasnoœæ ambient
static double fMoveLight; //numer dnia w roku albo -1
static bool bSmoothTraction; //wyg³adzanie drutów
static double fSunDeclination; //deklinacja S³oñca
static double fTimeSpeed; //przyspieszenie czasu, zmienna do testów
static double fTimeAngleDeg; //godzina w postaci k¹ta
static float fClockAngleDeg[6]; //k¹ty obrotu cylindrów dla zegara cyfrowego
static double fLatitudeDeg; //szerokoϾ geograficzna
static char* szTexturesTGA[4]; //lista tekstur od TGA
static char* szTexturesDDS[4]; //lista tekstur od DDS
static int iMultisampling; //tryb antyaliasingu: 0=brak,1=2px,2=4px,3=8px,4=16px
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 bool bActive; //czy jest aktywnym oknem
static void __fastcall 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
static int iTextures; //licznik u¿ytych tekstur
static int iSlowMotionMask; //maska wy³¹czanych w³aœciwoœci
static int iModifyTGA; //czy korygowaæ pliki TGA dla szybszego wczytywania
static bool bHideConsole; //hunter-271211: ukrywanie konsoli
static TWorld *pWorld; //wskaŸnik na œwiat do usuwania pojazdów
static TAnimModel *pTerrainCompact; //obiekt terenu do ewentualnego zapisania w pliku
static AnsiString asTerrainModel; //nazwa obiektu terenu do zapisania w pliku
static bool bRollFix; //czy wykonaæ przeliczanie przechy³ki
static Queryparsercomp::TQueryParserComp *qParser;
static cParser *pParser;
static int iSegmentsRendered; //iloœæ segmentów do regulacji wydajnoœci
static double fFpsAverage; //oczekiwana wartosæ FPS
static double fFpsDeviation; //odchylenie standardowe FPS
static double fFpsMin; //dolna granica FPS, przy której promieñ scenerii bêdzie zmniejszany
static double fFpsMax; //górna granica FPS, przy której promieñ scenerii bêdzie zwiêkszany
static double fFpsRadiusMax; //maksymalny promieñ renderowania
static int iFpsRadiusMax; //maksymalny promieñ renderowania w rozmiarze tabeli sektorów
static double fRadiusFactor; //wspó³czynnik zmiany promienia
static TCamera *pCamera; //parametry kamery
static TDynamicObject *pUserDynamic; //pojazd u¿ytkownika, renderowany bez trzêsienia
static double fCalibrateIn[6][4]; //parametry kalibracyjne wejϾ z pulpitu
static double fCalibrateOut[7][4]; //parametry kalibracyjne wyjϾ dla pulpitu
static double fBrakeStep; //krok zmiany hamulca dla klawiszy [Num3] i [Num9]
static bool bJoinEvents; //czy grupowaæ eventy o tych samych nazwach
static bool bSmudge; //czy wyœwietlaæ smugê, a pojazd u¿ytkownika na koñcu
static AnsiString asTranscript[5]; //napisy na ekranie (widoczne)
static TTranscripts tranTexts; //obiekt obs³uguj¹cy stenogramy dŸwiêków na ekranie
static AnsiString asLang; //domyœlny jêzyk - http://tools.ietf.org/html/bcp47
static int iHiddenEvents; //czy ³¹czyæ eventy z torami poprzez nazwê toru
static TTextSound *tsRadioBusy[10]; //zajêtoœæ kana³ów radiowych (wskaŸnik na odgrywany dŸwiêk)
//metody
static void __fastcall TrainDelete(TDynamicObject *d);
static void __fastcall ConfigParse(Queryparsercomp::TQueryParserComp *qp,cParser *cp=NULL);
static AnsiString __fastcall GetNextSymbol();
static TDynamicObject* __fastcall DynamicNearest();
static TDynamicObject* __fastcall CouplerNearest();
static bool __fastcall AddToQuery(TEvent *event,TDynamicObject *who);
static bool __fastcall DoEvents();
static AnsiString __fastcall Bezogonkow(AnsiString str, bool _=false);
};
//---------------------------------------------------------------------------
#endif

4511
Ground.cpp Normal file

File diff suppressed because it is too large Load Diff

367
Ground.h Normal file
View File

@@ -0,0 +1,367 @@
//---------------------------------------------------------------------------
#ifndef groundH
#define groundH
#include "dumb3d.h"
#include "ResourceManager.h"
#include "VBO.h"
#include "Classes.h"
using namespace Math3D;
//Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie
const int TP_MODEL=10;
const int TP_MESH=11; //Ra: specjalny obiekt grupojący siatki dla tekstury
const int TP_DUMMYTRACK=12; //Ra: zdublowanie obiektu toru dla rozdzielenia tekstur
const int TP_TERRAIN=13; //Ra: specjalny model dla terenu
const int TP_DYNAMIC=14;
const int TP_SOUND=15;
const int TP_TRACK=16;
//const int TP_GEOMETRY=17;
const int TP_MEMCELL=18;
const int TP_EVLAUNCH=19; //MC
const int TP_TRACTION=20;
const int TP_TRACTIONPOWERSOURCE=21; //MC
//const int TP_ISOLATED=22; //Ra
const int TP_SUBMODEL=22; //Ra: submodele terenu
const int TP_LAST=25; //rozmiar tablicy
struct DaneRozkaz
{//struktura komunikacji z EU07.EXE
int iSygn; //sygnatura 'EU07'
int iComm; //rozkaz/status (kod ramki)
union
{float fPar[62];
int iPar[62];
char cString[248]; //upakowane stringi
};
};
typedef int TGroundNodeType;
struct TGroundVertex
{
vector3 Point;
vector3 Normal;
float tu,tv;
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);
Normal=0.5*(v1.Normal+v2.Normal);
tu=0.5*(v1.tu+v2.tu);
tv=0.5*(v1.tv+v2.tv);
}
void SetByX(const TGroundVertex &v1,const TGroundVertex &v2,double x)
{//wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
double i=(x-v1.Point.x)/(v2.Point.x-v1.Point.x); //parametr równania
double j=1.0-i;
Point=j*v1.Point+i*v2.Point;
Normal=j*v1.Normal+i*v2.Normal;
tu=j*v1.tu+i*v2.tu;
tv=j*v1.tv+i*v2.tv;
}
void SetByZ(const TGroundVertex &v1,const TGroundVertex &v2,double z)
{//wyliczenie współrzędnych i mapowania punktu na odcinku v1<->v2
double i=(z-v1.Point.z)/(v2.Point.z-v1.Point.z); //parametr równania
double j=1.0-i;
Point=j*v1.Point+i*v2.Point;
Normal=j*v1.Normal+i*v2.Normal;
tu=j*v1.tu+i*v2.tu;
tv=j*v1.tv+i*v2.tv;
}
};
class TSubRect; //sektor (aktualnie 200m×200m, ale może być zmieniony)
class TGroundNode : public Resource
{//obiekt scenerii
private:
public:
TGroundNodeType iType; //typ obiektu
union
{//Ra: wskażniki zależne od typu - zrobić klasy dziedziczone zamiast
void *Pointer; //do przypisywania NULL
TSubModel *smTerrain; //modele terenu (kwadratow kilometrowych)
TAnimModel *Model; //model z animacjami
TDynamicObject *DynamicObject; //pojazd
vector3 *Points; //punkty dla linii
TTrack *pTrack; //trajektoria ruchu
TGroundVertex *Vertices; //wierzchołki dla trójkątów
TMemCell *MemCell; //komórka pamięci
TEventLauncher *EvLaunch; //wyzwalacz zdarzeń
TTraction *hvTraction; //drut zasilający
TTractionPowerSource *psTractionPowerSource; //zasilanie drutu (zaniedbane w sceneriach)
TTextSound *tsStaticSound; //dźwięk przestrzenny
TGroundNode *nNode; //obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
};
AnsiString asName; //nazwa (nie zawsze ma znaczenie)
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 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
bool PROBLEND;
int iVboPtr; //indeks w buforze VBO
GLuint TextureID; //główna (jedna) tekstura obiektu
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
__fastcall TGroundNode();
__fastcall TGroundNode(TGroundNodeType t,int n=0);
__fastcall ~TGroundNode();
void __fastcall Init(int n);
void __fastcall InitCenter(); //obliczenie współrzędnych środka
void __fastcall InitNormals();
void __fastcall MoveMe(vector3 pPosition); //przesuwanie (nie działa)
//bool __fastcall Disable();
inline TGroundNode* __fastcall Find(const AnsiString &asNameToFind,TGroundNodeType iNodeType)
{//wyszukiwanie czołgowe z typem
if ((iNodeType==iType)&&(asNameToFind==asName))
return this;
else
if (nNext) return nNext->Find(asNameToFind,iNodeType);
return NULL;
};
void __fastcall Compile(bool many=false);
void Release();
bool __fastcall GetTraction();
void __fastcall RenderHidden(); //obsługa dźwięków i wyzwalaczy zdarzeń
void __fastcall RenderDL(); //renderowanie nieprzezroczystych w Display Lists
void __fastcall RenderAlphaDL(); //renderowanie przezroczystych w Display Lists (McZapkie-131202)
void __fastcall RaRenderVBO(); //renderowanie (nieprzezroczystych) ze wspólnego VBO
void __fastcall RenderVBO(); //renderowanie nieprzezroczystych z własnego VBO
void __fastcall RenderAlphaVBO(); //renderowanie przezroczystych z (własnego) VBO
};
class TSubRect : public Resource, public CMesh
{//sektor składowy kwadratu kilometrowego
public:
int iTracks; //ilość torów w (tTracks)
TTrack **tTracks; //tory do renderowania pojazdów
protected:
TTrack *tTrackAnim; //obiekty do przeliczenia animacji
TGroundNode *nRootMesh; //obiekty renderujące wg tekstury (wtórne, lista po nNext2)
TGroundNode *nMeshed; //lista obiektów dla których istnieją obiekty renderujące grupowo
public:
TGroundNode *nRootNode; //wszystkie obiekty w sektorze, z wyjątkiem renderujących i pojazdów (nNext2)
TGroundNode *nRenderHidden; //lista obiektów niewidocznych, "renderowanych" również z tyłu (nNext3)
TGroundNode *nRenderRect; //z poziomu sektora - nieprzezroczyste (nNext3)
TGroundNode *nRenderRectAlpha; //z poziomu sektora - przezroczyste (nNext3)
TGroundNode *nRenderWires; //z poziomu sektora - druty i inne linie (nNext3)
TGroundNode *nRender; //indywidualnie - nieprzezroczyste (nNext3)
TGroundNode *nRenderMixed; //indywidualnie - nieprzezroczyste i przezroczyste (nNext3)
TGroundNode *nRenderAlpha; //indywidualnie - przezroczyste (nNext3)
int iNodeCount; //licznik obiektów, do pomijania pustych sektorów
public:
void __fastcall LoadNodes(); //utworzenie VBO sektora
public:
__fastcall TSubRect();
virtual __fastcall ~TSubRect();
virtual void Release(); //zwalnianie VBO sektora
void __fastcall NodeAdd(TGroundNode *Node); //dodanie obiektu do sektora na etapie rozdzielania na sektory
void __fastcall RaNodeAdd(TGroundNode *Node); //dodanie obiektu do listy renderowania
void __fastcall Sort(); //optymalizacja obiektów w sektorze (sortowanie wg tekstur)
TTrack* __fastcall FindTrack(vector3 *Point,int &iConnection,TTrack *Exclude);
TTraction* __fastcall FindTraction(vector3 *Point,int &iConnection,TTraction *Exclude);
bool __fastcall StartVBO(); //ustwienie VBO sektora dla (nRenderRect), (nRenderRectAlpha) i (nRenderWires)
bool __fastcall RaTrackAnimAdd(TTrack *t); //zgłoszenie toru do animacji
void __fastcall RaAnimate(); //przeliczenie animacji torów
void __fastcall RenderDL(); //renderowanie nieprzezroczystych w Display Lists
void __fastcall RenderAlphaDL(); //renderowanie przezroczystych w Display Lists (McZapkie-131202)
void __fastcall RenderVBO(); //renderowanie nieprzezroczystych z własnego VBO
void __fastcall RenderAlphaVBO(); //renderowanie przezroczystych z (własnego) VBO
void __fastcall RenderSounds(); //dźwięki pojazdów z niewidocznych sektorów
};
//Ra: trzeba sprawdzić wydajność siatki
const int iNumSubRects=5; //na ile dzielimy kilometr
const int iNumRects=500;
//const double fHalfNumRects=iNumRects/2.0; //połowa do wyznaczenia środka
const int iTotalNumSubRects=iNumRects*iNumSubRects;
const double fHalfTotalNumSubRects=iTotalNumSubRects/2.0;
const double fSubRectSize=1000.0/iNumSubRects;
const double fRectSize=fSubRectSize*iNumSubRects;
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
private:
int iLastDisplay; //numer klatki w której był ostatnio wyświetlany
TSubRect *pSubRects;
void __fastcall Init() { pSubRects=new TSubRect[iNumSubRects*iNumSubRects]; };
public:
static int iFrameNumber; //numer kolejny wyświetlanej klatki
TGroundNode *nTerrain; //model terenu z E3D - użyć nRootMesh?
__fastcall TGroundRect();
virtual __fastcall ~TGroundRect();
TSubRect* __fastcall SafeGetRect(int iCol,int iRow)
{//pobranie wskaźnika do małego kwadratu, utworzenie jeśli trzeba
if (!pSubRects) Init(); //utworzenie małych kwadratów
return pSubRects+iRow*iNumSubRects+iCol; //zwrócenie właściwego
};
TSubRect* __fastcall FastGetRect(int iCol,int iRow)
{//pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
return (pSubRects?pSubRects+iRow*iNumSubRects+iCol:NULL);
};
void __fastcall Optimize()
{//optymalizacja obiektów w sektorach
if (pSubRects)
for (int i=iNumSubRects*iNumSubRects-1;i>=0;--i)
pSubRects[i].Sort(); //optymalizacja obiektów w sektorach
};
void __fastcall RenderDL();
void __fastcall RenderVBO();
};
class TGround
{
vector3 CameraDirection; //zmienna robocza przy renderowaniu
int const *iRange; //tabela widoczności
//TGroundNode *nRootNode; //lista wszystkich węzłów
TGroundNode *nRootDynamic; //lista pojazdów
TGroundRect Rects[iNumRects][iNumRects]; //mapa kwadratów kilometrowych
TEvent *RootEvent; //lista zdarzeń
TEvent *QueryRootEvent,*tmpEvent,*tmp2Event,*OldQRE;
TSubRect *pRendered[1500]; //lista renderowanych sektorów
int iNumNodes;
vector3 pOrigin;
vector3 aRotate;
bool bInitDone;
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,mm,srh,srm,ssh,ssm; //ustawienia czasu
//int tracks,tracksfar; //liczniki torów
TNames *sTracks; //posortowane nazwy torów i eventów
private: //metody prywatne
bool __fastcall EventConditon(TEvent *e);
public:
bool bDynamicRemove; //czy uruchomić procedurę usuwania pojazdów
TDynamicObject *LastDyn; //ABu: paskudnie, ale na bardzo szybko moze jakos przejdzie...
//TTrain *pTrain;
//double fVDozwolona;
//bool bTrabil;
__fastcall TGround();
__fastcall ~TGround();
void __fastcall Free();
bool __fastcall Init(AnsiString asFile,HDC hDC);
void __fastcall FirstInit();
void __fastcall InitTracks();
void __fastcall InitTraction();
bool __fastcall InitEvents();
bool __fastcall InitLaunchers();
TTrack* __fastcall FindTrack(vector3 Point,int &iConnection,TGroundNode *Exclude);
TTraction* __fastcall FindTraction(vector3 *Point,int &iConnection,TGroundNode *Exclude);
TTraction* __fastcall TractionNearestFind(vector3 &p,int dir,TGroundNode *n);
//TGroundNode* __fastcall CreateGroundNode();
TGroundNode* __fastcall AddGroundNode(cParser* parser);
bool __fastcall AddGroundNode(double x,double z,TGroundNode *Node)
{
TSubRect *tmp=GetSubRect(x,z);
if (tmp)
{
tmp->NodeAdd(Node);
return true;
}
else
return false;
};
// bool __fastcall Include(TQueryParserComp *Parser);
//TGroundNode* __fastcall GetVisible(AnsiString asName);
TGroundNode* __fastcall GetNode(AnsiString asName);
bool __fastcall AddDynamic(TGroundNode *Node);
void __fastcall MoveGroundNode(vector3 pPosition);
void __fastcall UpdatePhys(double dt,int iter); //aktualizacja fizyki stałym krokiem
bool __fastcall Update(double dt,int iter); //aktualizacja przesunięć zgodna z FPS
bool __fastcall AddToQuery(TEvent *Event, TDynamicObject *Node);
bool __fastcall GetTraction(TDynamicObject *model);
bool __fastcall RenderDL(vector3 pPosition);
bool __fastcall RenderAlphaDL(vector3 pPosition);
bool __fastcall RenderVBO(vector3 pPosition);
bool __fastcall RenderAlphaVBO(vector3 pPosition);
bool __fastcall CheckQuery();
// __fastcall GetRect(double x, double z) { return &(Rects[int(x/fSubRectSize+fHalfNumRects)][int(z/fSubRectSize+fHalfNumRects)]); };
/*
int __fastcall GetRowFromZ(double z) { return (z/fRectSize+fHalfNumRects); };
int __fastcall GetColFromX(double x) { return (x/fRectSize+fHalfNumRects); };
int __fastcall GetSubRowFromZ(double z) { return (z/fSubRectSize+fHalfNumSubRects); };
int __fastcall GetSubColFromX(double x) { return (x/fSubRectSize+fHalfNumSubRects); };
*/
/*
inline TGroundNode* __fastcall FindGroundNode(const AnsiString &asNameToFind )
{
if (RootNode)
return (RootNode->Find( asNameToFind ));
else
return NULL;
}
*/
TGroundNode* __fastcall DynamicFindAny(AnsiString asNameToFind);
TGroundNode* __fastcall DynamicFind(AnsiString asNameToFind);
void __fastcall DynamicList(bool all=false);
TGroundNode* __fastcall FindGroundNode(AnsiString asNameToFind,TGroundNodeType iNodeType);
TGroundRect* __fastcall GetRect(double x, double z) { return &Rects[GetColFromX(x)/iNumSubRects][GetRowFromZ(z)/iNumSubRects]; };
TSubRect* __fastcall GetSubRect(double x, double z) { return GetSubRect(GetColFromX(x),GetRowFromZ(z)); };
TSubRect* __fastcall FastGetSubRect(double x, double z) { return FastGetSubRect(GetColFromX(x),GetRowFromZ(z)); };
TSubRect* __fastcall GetSubRect(int iCol, int iRow);
TSubRect* __fastcall FastGetSubRect(int iCol, int iRow);
int __fastcall GetRowFromZ(double z) { return (z/fSubRectSize+fHalfTotalNumSubRects); };
int __fastcall GetColFromX(double x) { return (x/fSubRectSize+fHalfTotalNumSubRects); };
TEvent* __fastcall FindEvent(const AnsiString &asEventName);
TEvent* __fastcall FindEventScan(const AnsiString &asEventName);
void __fastcall TrackJoin(TGroundNode *Current);
private:
void __fastcall OpenGLUpdate(HDC hDC);
void __fastcall RaTriangleDivider(TGroundNode* node);
void __fastcall Navigate(String ClassName,UINT Msg,WPARAM wParam,LPARAM lParam);
bool PROBLEND;
public:
void __fastcall WyslijEvent(const AnsiString &e,const AnsiString &d);
int iRendered; //ilość renderowanych sektorów, pobierana przy pokazywniu FPS
void __fastcall WyslijString(const AnsiString &t,int n);
void __fastcall WyslijWolny(const AnsiString &t);
void __fastcall WyslijNamiary(TGroundNode* t);
void __fastcall WyslijParam(int nr,int fl);
void __fastcall RadioStop(vector3 pPosition);
TDynamicObject* __fastcall DynamicNearest(vector3 pPosition,double distance=20.0,bool mech=false);
TDynamicObject* __fastcall CouplerNearest(vector3 pPosition,double distance=20.0,bool mech=false);
void __fastcall DynamicRemove(TDynamicObject* dyn);
void __fastcall TerrainRead(const AnsiString &f);
void __fastcall TerrainWrite();
void __fastcall TrackBusyList();
void __fastcall IsolatedBusyList();
void __fastcall IsolatedBusy(const AnsiString t);
void __fastcall Silence(vector3 gdzie);
};
//---------------------------------------------------------------------------
#endif

94
Logs.cpp Normal file
View File

@@ -0,0 +1,94 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Logs.h"
#include "Globals.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
std::ofstream output; //standardowy "log.txt", mo¿na go wy³¹czyæ
std::ofstream errors; //lista b³êdów "errors.txt", zawsze dzia³a
char endstring[10]="\n";
void __fastcall WriteConsoleOnly(const char* str, double value)
{
char buf[255];
sprintf(buf,"%s %f \n",str,value);
//stdout= GetStdHandle(STD_OUTPUT_HANDLE);
DWORD wr= 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),buf,strlen(buf),&wr,NULL);
//WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),endstring,strlen(endstring),&wr,NULL);
}
void __fastcall WriteConsoleOnly(const char* str)
{
//printf("%n ffafaf /n",str);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY);
DWORD wr= 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),str,strlen(str),&wr,NULL);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),endstring,strlen(endstring),&wr,NULL);
}
void __fastcall WriteLog(const char* str, double value)
{
if (Global::iWriteLogEnabled)
{
if (str)
{
char buf[255];
sprintf(buf,"%s %f",str,value);
WriteLog(buf);
}
}
};
void __fastcall WriteLog(const char* str)
{
if (str)
{
if (Global::iWriteLogEnabled&1)
{if (!output.is_open())
output.open("log.txt",std::ios::trunc);
output << str << "\n";
output.flush();
}
//hunter-271211: pisanie do konsoli tylko, gdy nie jest ukrywana
if (Global::iWriteLogEnabled&2)
WriteConsoleOnly(str);
}
};
void __fastcall ErrorLog(const char* str)
{//Ra: bezwarunkowa rejestracja powa¿nych b³êdów
if (!errors.is_open())
{errors.open("errors.txt",std::ios::trunc);
errors << AnsiString("EU07.EXE "+Global::asRelease).c_str() << "\n";
}
if (str) errors << str;
errors << "\n";
errors.flush();
};
void __fastcall Error(const AnsiString &asMessage,bool box)
{
if (box)
MessageBox(NULL,asMessage.c_str(),AnsiString("EU07 "+Global::asRelease).c_str(),MB_OK);
WriteLog(asMessage.c_str());
}
void __fastcall ErrorLog(const AnsiString &asMessage)
{//zapisywanie b³êdów "errors.txt"
ErrorLog(asMessage.c_str());
WriteLog(asMessage.c_str()); //do "log.txt" ewentualnie te¿
}
void __fastcall WriteLog(const AnsiString &str)
{//Ra: wersja z AnsiString jest zamienna z Error()
WriteLog(str.c_str());
};
//---------------------------------------------------------------------------
#pragma package(smart_init)

15
Logs.h Normal file
View File

@@ -0,0 +1,15 @@
//---------------------------------------------------------------------------
#ifndef LogsH
#define LogsH
#include <system.hpp>
void __fastcall WriteConsoleOnly(const char *str, double value);
void __fastcall WriteConsoleOnly(const char *str);
void __fastcall WriteLog(const char *str, double value);
void __fastcall WriteLog(const char *str);
void __fastcall Error(const AnsiString &asMessage,bool box=true);
void __fastcall ErrorLog(const AnsiString &asMessage);
void __fastcall WriteLog(const AnsiString &str);
//---------------------------------------------------------------------------
#endif

94
Machajka.cpp Normal file
View File

@@ -0,0 +1,94 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Machajka.h"
#include "Timer.h"
#include "Globals.h"
__fastcall TMachajka::TMachajka():TTrain()
{
TTrain::TTrain();
}
__fastcall TMachajka::~TMachajka()
{
}
bool __fastcall TMachajka::Init(TDynamicObject *NewDynamicObject)
{
TTrain::Init(NewDynamicObject);
return true;
}
void __fastcall TMachajka::OnKeyPress(int cKey)
{
if (!GetAsyncKeyState(VK_SHIFT)<0) //bez shifta
{
if (cKey==Global::Keys[k_IncMainCtrl])
(DynamicObject->MoverParameters->AddPulseForce(1));
else
if (cKey==Global::Keys[k_DecMainCtrl])
(DynamicObject->MoverParameters->AddPulseForce(-1));
else
if (cKey==Global::Keys[k_IncLocalBrakeLevel])
(DynamicObject->MoverParameters->IncLocalBrakeLevel(1));
else
if (cKey==Global::Keys[k_DecLocalBrakeLevel])
(DynamicObject->MoverParameters->DecLocalBrakeLevel(1));
else
if (cKey==Global::Keys[k_MechLeft])
vMechMovement.x+=fMechCroach;
else
if (cKey==Global::Keys[k_MechRight])
vMechMovement.x-=fMechCroach;
else
if (cKey==Global::Keys[k_MechBackward])
vMechMovement.z-=fMechCroach;
else
if (cKey==Global::Keys[k_MechForward])
vMechMovement.z+=fMechCroach;
else
if (cKey==Global::Keys[k_MechUp])
pMechOffset.y+=0.3; //McZapkie-120302 - wstawanie
else
if (cKey==Global::Keys[k_MechDown])
pMechOffset.y-=0.3; //McZapkie-120302 - siadanie, kucanie itp
}
else //z shiftem
{
if (cKey==Global::Keys[k_IncMainCtrlFAST])
(DynamicObject->MoverParameters->AddPulseForce(2));
else
if (cKey==Global::Keys[k_DecMainCtrlFAST])
(DynamicObject->MoverParameters->AddPulseForce(-2));
else
if (cKey==Global::Keys[k_IncLocalBrakeLevelFAST])
(DynamicObject->MoverParameters->IncLocalBrakeLevel(2));
else
if (cKey==Global::Keys[k_DecLocalBrakeLevelFAST])
(DynamicObject->MoverParameters->DecLocalBrakeLevel(2));
}
}
bool __fastcall TMachajka::Update(double dt)
{
TTrain::Update(dt);
}
bool __fastcall TMachajka::UpdateMechPosition()
{
TTrain::UpdateMechPosition();
}
bool __fastcall TMachajka::Render()
{
TTrain::Render();
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

30
Machajka.h Normal file
View File

@@ -0,0 +1,30 @@
//---------------------------------------------------------------------------
#ifndef MachajkaH
#define MachajkaH
#include "Train.h"
class TMachajka:public TTrain
{
public:
TSubModel *wajcha;
// double v;
// double m;
// double a;
// double f;
// bool enter;
// bool space;
// double wa,wv;
__fastcall TMachajka();
virtual __fastcall ~TMachajka();
virtual bool __fastcall Init(TDynamicObject *NewDynamicObject);
virtual void __fastcall OnKeyPress(int cKey);
virtual bool __fastcall Update(double dt);
virtual bool __fastcall UpdateMechPosition();
virtual bool __fastcall Render();
};
//---------------------------------------------------------------------------
#endif

882
McZapkie/Mover.hpp Normal file
View File

@@ -0,0 +1,882 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) '_mover.pas' rev: 5.00
//Ra: eee... tam, sam siê generuje b³êdnie i trzeba rêcznie poprawiaæ!
#ifndef _moverHPP
#define _moverHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <Oerlikon_ESt.hpp> // Pascal unit
#include <hamulce.hpp> // Pascal unit
#include <SysUtils.hpp> // Pascal unit
#include <mctools.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace _mover
{
//-- type declarations -------------------------------------------------------
struct TLocation
{
double X;
double Y;
double Z;
} ;
struct TRotation
{
double Rx;
double Ry;
double Rz;
} ;
struct TDimension
{
double W;
double L;
double H;
} ;
struct TCommand
{
AnsiString Command;
double Value1;
double Value2;
TLocation Location;
} ;
struct TTrackShape
{
double R;
double Len;
double dHtrack;
double dHrail;
} ;
struct TTrackParam
{
double Width;
double friction;
Byte CategoryFlag;
Byte QualityFlag;
Byte DamageFlag;
double Velmax;
} ;
struct TTractionParam
{
double TractionVoltage;
double TractionFreq;
double TractionMaxCurrent;
double TractionResistivity;
} ;
#pragma option push -b-
enum TBrakeSystem { Individual, Pneumatic, ElectroPneumatic };
#pragma option pop
#pragma option push -b-
enum TBrakeSubSystem { ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako };
#pragma option pop
#pragma option push -b-
enum TBrakeValve { NoValve, W, W_Lu_VI, W_Lu_L, W_Lu_XR, K, Kg, Kp, Kss, Kkg, Kkp, Kks, Hikg1, Hikss,
Hikp1, KE, SW, EStED, NESt3, ESt3, LSt, ESt4, ESt3AL2, EP1, EP2, M483, CV1_L_TR, CV1, CV1_R, Other
};
#pragma option pop
#pragma option push -b-
enum TBrakeHandle { NoHandle, West, FV4a, M394, M254, FVel1, FVel6, D2, Knorr, FD1, BS2, testH, St113
};
#pragma option pop
#pragma option push -b-
enum TLocalBrake { NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake };
#pragma option pop
typedef double TBrakeDelayTable[4];
struct TBrakePressure
{
double PipePressureVal;
double BrakePressureVal;
double FlowSpeedVal;
TBrakeSystem BrakeType;
} ;
typedef TBrakePressure TBrakePressureTable[13];
#pragma option push -b-
enum TEngineTypes { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine,
SteamEngine, DieselElectric };
#pragma option pop
#pragma option push -b-
enum TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower };
#pragma option pop
#pragma option push -b-
enum TFuelType { Undefined, Coal, Oil };
#pragma option pop
struct TGrateType
{
TFuelType FuelType;
double GrateSurface;
double FuelTransportSpeed;
double IgnitionTemperature;
double MaxTemperature;
} ;
struct TBoilerType
{
double BoilerVolume;
double BoilerHeatSurface;
double SuperHeaterSurface;
double MaxWaterVolume;
double MinWaterVolume;
double MaxPressure;
} ;
struct TCurrentCollector
{
int CollectorsNo;
double MinH;
double MaxH;
double CSW;
double MinV;
double MaxV;
double InsetV;
double MinPress;
double MaxPress;
} ;
#pragma option push -b-
enum TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector,
PowerCable, Heater };
#pragma option pop
struct _mover__1
{
double MaxCapacity;
TPowerSource RechargeSource;
} ;
struct _mover__2
{
TPowerType PowerTrans;
double SteamPressure;
} ;
struct _mover__3
{
TGrateType Grate;
TBoilerType Boiler;
} ;
struct TPowerParameters
{
double MaxVoltage;
double MaxCurrent;
double IntR;
TPowerSource SourceType;
union
{
struct
{
_mover__3 RHeater;
};
struct
{
_mover__2 RPowerCable;
};
struct
{
TCurrentCollector CollectorParameters;
};
struct
{
_mover__1 RAccumulator;
};
struct
{
TEngineTypes GeneratorEngine;
};
struct
{
double InputVoltage;
};
struct
{
TPowerType PowerType;
};
};
} ;
struct TScheme
{
Byte Relay;
double R;
Byte Bn;
Byte Mn;
bool AutoSwitch;
Byte ScndAct;
} ;
typedef TScheme TSchemeTable[65];
struct TDEScheme
{
double RPM;
double GenPower;
double Umax;
double Imax;
} ;
typedef TDEScheme TDESchemeTable[33];
struct TShuntScheme
{
double Umin;
double Umax;
double Pmin;
double Pmax;
} ;
typedef TShuntScheme TShuntSchemeTable[33];
struct TMPTRelay
{
double Iup;
double Idown;
} ;
typedef TMPTRelay TMPTRelayTable[8];
struct TMotorParameters
{
double mfi;
double mIsat;
double mfi0;
double fi;
double Isat;
double fi0;
bool AutoSwitch;
} ;
struct TSecuritySystem
{
Byte SystemType;
double AwareDelay;
double AwareMinSpeed;
double SoundSignalDelay;
double EmergencyBrakeDelay;
Byte Status;
double SystemTimer;
double SystemSoundCATimer;
double SystemSoundSHPTimer;
double SystemBrakeCATimer;
double SystemBrakeSHPTimer;
double SystemBrakeCATestTimer;
int VelocityAllowed;
int NextVelocityAllowed;
bool RadioStop;
} ;
struct TTransmision
{
Byte NToothM;
Byte NToothW;
double Ratio;
} ;
#pragma option push -b-
enum TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic };
#pragma option pop
class DELPHICLASS T_MoverParameters;
struct TCoupling
{
double SpringKB;
double SpringKC;
double beta;
double DmaxB;
double FmaxB;
double DmaxC;
double FmaxC;
TCouplerType CouplerType;
Byte CouplingFlag;
int AllowedFlag;
bool Render;
double CoupleDist;
T_MoverParameters* Connected;
Byte ConnectedNr;
double CForce;
double Dist;
bool CheckCollision;
} ;
class PASCALIMPLEMENTATION T_MoverParameters : public System::TObject
{
typedef System::TObject inherited;
public:
double dMoveLen;
AnsiString filename;
Byte CategoryFlag;
AnsiString TypeName;
int TrainType;
TEngineTypes EngineType;
TPowerParameters EnginePowerSource;
TPowerParameters SystemPowerSource;
TPowerParameters HeatingPowerSource;
TPowerParameters AlterHeatPowerSource;
TPowerParameters LightPowerSource;
TPowerParameters AlterLightPowerSource;
double Vmax;
double Mass;
double Power;
double Mred;
double TotalMass;
double HeatingPower;
double LightPower;
double BatteryVoltage;
bool Battery;
bool EpFuse;
bool Signalling;
bool DoorSignalling;
bool Radio;
double NominalBatteryVoltage;
TDimension Dim;
double Cx;
double Floor;
double WheelDiameter;
double WheelDiameterL;
double WheelDiameterT;
double TrackW;
double AxleInertialMoment;
AnsiString AxleArangement;
Byte NPoweredAxles;
Byte NAxles;
Byte BearingType;
double ADist;
double BDist;
Byte NBpA;
int SandCapacity;
TBrakeSystem BrakeSystem;
TBrakeSubSystem BrakeSubsystem;
TBrakeValve BrakeValve;
TBrakeHandle BrakeHandle;
TBrakeHandle BrakeLocHandle;
double MBPM;
Hamulce::TBrake* Hamulec;
Hamulce::THandle* Handle;
Hamulce::THandle* LocHandle;
Hamulce::TReservoir* Pipe;
Hamulce::TReservoir* Pipe2;
TLocalBrake LocalBrake;
TBrakePressure BrakePressureTable[13];
TBrakePressure BrakePressureActual;
Byte ASBType;
Byte TurboTest;
double MaxBrakeForce;
double MaxBrakePress[5];
double P2FTrans;
double TrackBrakeForce;
Byte BrakeMethod;
double HighPipePress;
double LowPipePress;
double DeltaPipePress;
double CntrlPipePress;
double BrakeVolume;
double BrakeVVolume;
double VeselVolume;
int BrakeCylNo;
double BrakeCylRadius;
double BrakeCylDist;
double BrakeCylMult[3];
Byte LoadFlag;
double BrakeCylSpring;
double BrakeSlckAdj;
double BrakeRigEff;
double RapidMult;
int BrakeValveSize;
AnsiString BrakeValveParams;
double Spg;
double MinCompressor;
double MaxCompressor;
double CompressorSpeed;
double BrakeDelay[4];
Byte BrakeCtrlPosNo;
Byte MainCtrlPosNo;
Byte ScndCtrlPosNo;
bool ScndInMain;
bool MBrake;
TSecuritySystem SecuritySystem;
TScheme RList[65];
int RlistSize;
TMotorParameters MotorParam[11];
TTransmision Transmision;
double NominalVoltage;
double WindingRes;
double u;
double CircuitRes;
int IminLo;
int IminHi;
int ImaxLo;
int ImaxHi;
double nmax;
double InitialCtrlDelay;
double CtrlDelay;
double CtrlDownDelay;
Byte FastSerialCircuit;
Byte AutoRelayType;
bool CoupledCtrl;
bool IsCoupled;
Byte DynamicBrakeType;
Byte RVentType;
double RVentnmax;
double RVentCutOff;
int CompressorPower;
int SmallCompressorPower;
double dizel_Mmax;
double dizel_nMmax;
double dizel_Mnmax;
double dizel_nmax;
double dizel_nominalfill;
double dizel_Mstand;
double dizel_nmax_cutoff;
double dizel_nmin;
double dizel_minVelfullengage;
double dizel_AIM;
double dizel_engageDia;
double dizel_engageMaxForce;
double dizel_engagefriction;
double AnPos;
bool AnalogCtrl;
bool AnMainCtrl;
bool ShuntModeAllow;
bool ShuntMode;
bool Flat;
double Vhyp;
TDEScheme DElist[33];
double Vadd;
TMPTRelay MPTRelay[8];
Byte RelayType;
TShuntScheme SST[33];
double PowerCorRatio;
double Ftmax;
double eimc[21];
int MaxLoad;
AnsiString LoadAccepted;
AnsiString LoadQuantity;
double OverLoadFactor;
double LoadSpeed;
double UnLoadSpeed;
Byte DoorOpenCtrl;
Byte DoorCloseCtrl;
double DoorStayOpen;
bool DoorClosureWarning;
double DoorOpenSpeed;
double DoorCloseSpeed;
double DoorMaxShiftL;
double DoorMaxShiftR;
Byte DoorOpenMethod;
bool ScndS;
TLocation Loc;
TRotation Rot;
AnsiString Name;
TCoupling Couplers[2];
double HVCouplers[2][2];
int ScanCounter;
bool EventFlag;
Byte SoundFlag;
double DistCounter;
double V;
double Vel;
double AccS;
double AccN;
double AccV;
double nrot;
double EnginePower;
double dL;
double Fb;
double Ff;
double FTrain;
double FStand;
double FTotal;
double UnitBrakeForce;
double Ntotal;
bool SlippingWheels;
bool SandDose;
double Sand;
double BrakeSlippingTimer;
double dpBrake;
double dpPipe;
double dpMainValve;
double dpLocalValve;
double ScndPipePress;
double BrakePress;
double LocBrakePress;
double PipeBrakePress;
double PipePress;
double EqvtPipePress;
double Volume;
double CompressedVolume;
double PantVolume;
double Compressor;
bool CompressorFlag;
bool PantCompFlag;
bool CompressorAllow;
bool ConverterFlag;
bool ConverterAllow;
int BrakeCtrlPos;
double BrakeCtrlPosR;
double BrakeCtrlPos2;
Byte LocalBrakePos;
Byte ManualBrakePos;
double LocalBrakePosA;
Byte BrakeStatus;
bool EmergencyBrakeFlag;
Byte BrakeDelayFlag;
Byte BrakeDelays;
bool DynamicBrakeFlag;
double LimPipePress;
double ActFlowSpeed;
Byte DamageFlag;
Byte DerailReason;
TCommand CommandIn;
AnsiString CommandOut;
AnsiString CommandLast;
double ValueOut;
TTrackShape RunningShape;
TTrackParam RunningTrack;
double OffsetTrackH;
double OffsetTrackV;
bool Mains;
Byte MainCtrlPos;
Byte ScndCtrlPos;
int ActiveDir;
int CabNo;
int DirAbsolute;
int ActiveCab;
double LastSwitchingTime;
bool DepartureSignal;
bool InsideConsist;
TTractionParam RunningTraction;
double enrot;
double Im;
double Itot;
double IHeating;
double ITraction;
double TotalCurrent;
double Mm;
double Mw;
double Fw;
double Ft;
int Imin;
int Imax;
double Voltage;
Byte MainCtrlActualPos;
Byte ScndCtrlActualPos;
bool DelayCtrlFlag;
double LastRelayTime;
bool AutoRelayFlag;
bool FuseFlag;
bool ConvOvldFlag;
bool StLinFlag;
bool ResistorsFlag;
double RventRot;
bool UnBrake;
double PantPress;
bool s_CAtestebrake;
double dizel_fill;
double dizel_engagestate;
double dizel_engage;
double dizel_automaticgearstatus;
bool dizel_enginestart;
double dizel_engagedeltaomega;
double eimv[21];
double PulseForce;
double PulseForceTimer;
int PulseForceCount;
double eAngle;
int Load;
AnsiString LoadType;
Byte LoadStatus;
double LastLoadChangeTime;
bool DoorBlocked;
bool DoorLeftOpened;
bool DoorRightOpened;
bool PantFrontUp;
bool PantRearUp;
bool PantFrontSP;
bool PantRearSP;
int PantFrontStart;
int PantRearStart;
double PantFrontVolt;
double PantRearVolt;
AnsiString PantSwitchType;
AnsiString ConvSwitchType;
bool Heating;
int DoubleTr;
bool PhysicActivation;
double FrictConst1;
double FrictConst2s;
double FrictConst2d;
double TotalMassxg;
double __fastcall GetTrainsetVoltage(void);
bool __fastcall Physic_ReActivation(void);
double __fastcall LocalBrakeRatio(void);
double __fastcall ManualBrakeRatio(void);
double __fastcall PipeRatio(void);
double __fastcall RealPipeRatio(void);
double __fastcall BrakeVP(void);
bool __fastcall DynamicBrakeSwitch(bool Switch);
bool __fastcall SendCtrlBroadcast(AnsiString CtrlCommand, double ctrlvalue);
bool __fastcall SendCtrlToNext(AnsiString CtrlCommand, double ctrlvalue, double dir);
bool __fastcall CabActivisation(void);
bool __fastcall CabDeactivisation(void);
bool __fastcall IncMainCtrl(int CtrlSpeed);
bool __fastcall DecMainCtrl(int CtrlSpeed);
bool __fastcall IncScndCtrl(int CtrlSpeed);
bool __fastcall DecScndCtrl(int CtrlSpeed);
bool __fastcall AddPulseForce(int Multipler);
bool __fastcall SandDoseOn(void);
bool __fastcall SecuritySystemReset(void);
void __fastcall SecuritySystemCheck(double dt);
bool __fastcall BatterySwitch(bool State);
bool __fastcall EpFuseSwitch(bool State);
bool __fastcall IncBrakeLevelOld(void);
bool __fastcall DecBrakeLevelOld(void);
bool __fastcall IncLocalBrakeLevel(Byte CtrlSpeed);
bool __fastcall DecLocalBrakeLevel(Byte CtrlSpeed);
bool __fastcall IncLocalBrakeLevelFAST(void);
bool __fastcall DecLocalBrakeLevelFAST(void);
bool __fastcall IncManualBrakeLevel(Byte CtrlSpeed);
bool __fastcall DecManualBrakeLevel(Byte CtrlSpeed);
bool __fastcall EmergencyBrakeSwitch(bool Switch);
bool __fastcall AntiSlippingBrake(void);
bool __fastcall BrakeReleaser(Byte state);
bool __fastcall SwitchEPBrake(Byte state);
bool __fastcall AntiSlippingButton(void);
bool __fastcall IncBrakePress(double &brake, double PressLimit, double dp);
bool __fastcall DecBrakePress(double &brake, double PressLimit, double dp);
bool __fastcall BrakeDelaySwitch(Byte BDS);
bool __fastcall IncBrakeMult(void);
bool __fastcall DecBrakeMult(void);
void __fastcall UpdateBrakePressure(double dt);
void __fastcall UpdatePipePressure(double dt);
void __fastcall CompressorCheck(double dt);
//void __fastcall UpdatePantVolume(double dt);
void __fastcall UpdateScndPipePressure(double dt);
void __fastcall UpdateBatteryVoltage(double dt);
double __fastcall GetDVc(double dt);
void __fastcall ComputeConstans(void);
double __fastcall ComputeMass(void);
double __fastcall Adhesive(double staticfriction);
double __fastcall TractionForce(double dt);
double __fastcall FrictionForce(double R, Byte TDamage);
double __fastcall BrakeForce(const TTrackParam &Track);
double __fastcall CouplerForce(Byte CouplerN, double dt);
void __fastcall CollisionDetect(Byte CouplerN, double dt);
double __fastcall ComputeRotatingWheel(double WForce, double dt, double n);
bool __fastcall SetInternalCommand(AnsiString NewCommand, double NewValue1, double NewValue2);
double __fastcall GetExternalCommand(AnsiString &Command);
bool __fastcall RunCommand(AnsiString command, double CValue1, double CValue2);
bool __fastcall RunInternalCommand(void);
void __fastcall PutCommand(AnsiString NewCommand, double NewValue1, double NewValue2, const TLocation
&NewLocation);
bool __fastcall DirectionBackward(void);
bool __fastcall MainSwitch(bool State);
bool __fastcall ConverterSwitch(bool State);
bool __fastcall CompressorSwitch(bool State);
bool __fastcall FuseOn(void);
bool __fastcall FuseFlagCheck(void);
void __fastcall FuseOff(void);
int __fastcall ShowCurrent(Byte AmpN);
double __fastcall v2n(void);
double __fastcall current(double n, double U);
double __fastcall Momentum(double I);
double __fastcall MomentumF(double I, double Iw, Byte SCP);
bool __fastcall CutOffEngine(void);
bool __fastcall MaxCurrentSwitch(bool State);
bool __fastcall ResistorsFlagCheck(void);
bool __fastcall MinCurrentSwitch(bool State);
bool __fastcall AutoRelaySwitch(bool State);
bool __fastcall AutoRelayCheck(void);
bool __fastcall dizel_EngageSwitch(double state);
bool __fastcall dizel_EngageChange(double dt);
bool __fastcall dizel_AutoGearCheck(void);
double __fastcall dizel_fillcheck(Byte mcp);
double __fastcall dizel_Momentum(double dizel_fill, double n, double dt);
bool __fastcall dizel_Update(double dt);
bool __fastcall LoadingDone(double LSpeed, AnsiString LoadInit);
void __fastcall ComputeTotalForce(double dt, double dt1, bool FullVer);
double __fastcall ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track
, TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot);
double __fastcall FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const
TLocation &NewLoc, TRotation &NewRot);
bool __fastcall ChangeOffsetH(double DeltaOffset);
__fastcall T_MoverParameters(double VelInitial, AnsiString TypeNameInit, AnsiString NameInit, int LoadInitial
, AnsiString LoadTypeInitial, int Cab);
bool __fastcall LoadChkFile(AnsiString chkpath);
bool __fastcall CheckLocomotiveParameters(bool ReadyFlag, int Dir);
AnsiString __fastcall EngineDescription(int what);
bool __fastcall DoorLeft(bool State);
bool __fastcall DoorRight(bool State);
bool __fastcall DoorBlockedFlag(void);
bool __fastcall PantFront(bool State);
bool __fastcall PantRear(bool State);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall T_MoverParameters(void) : System::TObject() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~T_MoverParameters(void) { }
#pragma option pop
};
//-- var, const, procedure ---------------------------------------------------
static const bool Go = true;
static const bool Hold = false;
static const Shortint ResArraySize = 0x40;
static const Shortint MotorParametersArraySize = 0xa;
static const Shortint maxcc = 0x4;
static const Shortint LocalBrakePosNo = 0xa;
static const Shortint MainBrakeMaxPos = 0xa;
static const Shortint ManualBrakePosNo = 0x14;
static const Shortint dtrack_railwear = 0x2;
static const Shortint dtrack_freerail = 0x4;
static const Shortint dtrack_thinrail = 0x8;
static const Shortint dtrack_railbend = 0x10;
static const Shortint dtrack_plants = 0x20;
static const Shortint dtrack_nomove = 0x40;
static const Byte dtrack_norail = 0x80;
static const Shortint dtrain_thinwheel = 0x1;
static const Shortint dtrain_loadshift = 0x1;
static const Shortint dtrain_wheelwear = 0x2;
static const Shortint dtrain_bearing = 0x4;
static const Shortint dtrain_coupling = 0x8;
static const Shortint dtrain_ventilator = 0x10;
static const Shortint dtrain_loaddamage = 0x10;
static const Shortint dtrain_engine = 0x20;
static const Shortint dtrain_loaddestroyed = 0x20;
static const Shortint dtrain_axle = 0x40;
static const Byte dtrain_out = 0x80;
#define p_elengproblem (1.000000E-02)
#define p_elengdamage (1.000000E-01)
#define p_coupldmg (2.000000E-02)
#define p_derail (1.000000E-03)
#define p_accn (1.000000E-01)
#define p_slippdmg (1.000000E-03)
static const Shortint ctrain_virtual = 0x0;
static const Shortint ctrain_coupler = 0x1;
static const Shortint ctrain_pneumatic = 0x2;
static const Shortint ctrain_controll = 0x4;
static const Shortint ctrain_power = 0x8;
static const Shortint ctrain_passenger = 0x10;
static const Shortint ctrain_scndpneumatic = 0x20;
static const Shortint ctrain_heating = 0x40;
static const Byte ctrain_depot = 0x80;
static const Shortint dbrake_none = 0x0;
static const Shortint dbrake_passive = 0x1;
static const Shortint dbrake_switch = 0x2;
static const Shortint dbrake_reversal = 0x4;
static const Shortint dbrake_automatic = 0x8;
static const Shortint s_waiting = 0x1;
static const Shortint s_aware = 0x2;
static const Shortint s_active = 0x4;
static const Shortint s_CAalarm = 0x8;
static const Shortint s_SHPalarm = 0x10;
static const Shortint s_CAebrake = 0x20;
static const Shortint s_SHPebrake = 0x40;
static const Byte s_CAtest = 0x80;
static const Shortint sound_none = 0x0;
static const Shortint sound_loud = 0x1;
static const Shortint sound_couplerstretch = 0x2;
static const Shortint sound_bufferclamp = 0x4;
static const Shortint sound_bufferbump = 0x8;
static const Shortint sound_relay = 0x10;
static const Shortint sound_manyrelay = 0x20;
static const Shortint sound_brakeacc = 0x40;
extern PACKAGE bool PhysicActivationFlag;
static const Shortint dt_Default = 0x0;
static const Shortint dt_EZT = 0x1;
static const Shortint dt_ET41 = 0x2;
static const Shortint dt_ET42 = 0x4;
static const Shortint dt_PseudoDiesel = 0x8;
static const Shortint dt_ET22 = 0x10;
static const Shortint dt_SN61 = 0x20;
static const Shortint dt_EP05 = 0x40;
static const Byte dt_ET40 = 0x80;
static const Word dt_181 = 0x100;
static const Shortint eimc_s_dfic = 0x0;
static const Shortint eimc_s_dfmax = 0x1;
static const Shortint eimc_s_p = 0x2;
static const Shortint eimc_s_cfu = 0x3;
static const Shortint eimc_s_cim = 0x4;
static const Shortint eimc_s_icif = 0x5;
static const Shortint eimc_f_Uzmax = 0x7;
static const Shortint eimc_f_uzh = 0x8;
static const Shortint eimc_f_DU = 0x9;
static const Shortint eimc_f_I0 = 0xa;
static const Shortint eimc_f_cfu = 0xb;
static const Shortint eimc_p_F0 = 0xd;
static const Shortint eimc_p_a1 = 0xe;
static const Shortint eimc_p_Pmax = 0xf;
static const Shortint eimc_p_Fh = 0x10;
static const Shortint eimc_p_Ph = 0x11;
static const Shortint eimc_p_Vh0 = 0x12;
static const Shortint eimc_p_Vh1 = 0x13;
static const Shortint eimc_p_Imax = 0x14;
static const Shortint eimv_FMAXMAX = 0x0;
static const Shortint eimv_Fmax = 0x1;
static const Shortint eimv_ks = 0x2;
static const Shortint eimv_df = 0x3;
static const Shortint eimv_fp = 0x4;
static const Shortint eimv_U = 0x5;
static const Shortint eimv_pole = 0x6;
static const Shortint eimv_Ic = 0x7;
static const Shortint eimv_If = 0x8;
static const Shortint eimv_M = 0x9;
static const Shortint eimv_Fr = 0xa;
static const Shortint eimv_Ipoj = 0xb;
static const Shortint eimv_Pm = 0xc;
static const Shortint eimv_Pe = 0xd;
static const Shortint eimv_eta = 0xe;
static const Shortint eimv_fkr = 0xf;
static const Shortint eimv_Uzsmax = 0x10;
static const Shortint eimv_Pmax = 0x11;
static const Shortint eimv_Fzad = 0x12;
static const Shortint eimv_Imax = 0x13;
extern PACKAGE double __fastcall Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension
&Dim1, const TDimension &Dim2);
} /* namespace _mover */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace _mover;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // _mover

293
McZapkie/Oerlikon_ESt.hpp Normal file
View File

@@ -0,0 +1,293 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) 'Oerlikon_ESt.pas' rev: 5.00
#ifndef Oerlikon_EStHPP
#define Oerlikon_EStHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <hamulce.hpp> // Pascal unit
#include <friction.hpp> // Pascal unit
#include <SysUtils.hpp> // Pascal unit
#include <mctools.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace Oerlikon_est
{
//-- type declarations -------------------------------------------------------
class DELPHICLASS TPrzekladnik;
class PASCALIMPLEMENTATION TPrzekladnik : public Hamulce::TReservoir
{
typedef Hamulce::TReservoir inherited;
public:
Hamulce::TReservoir* *BrakeRes;
Hamulce::TReservoir* *Next;
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TPrzekladnik(void) : Hamulce::TReservoir() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TPrzekladnik(void) { }
#pragma option pop
};
class DELPHICLASS TRura;
class PASCALIMPLEMENTATION TRura : public TPrzekladnik
{
typedef TPrzekladnik inherited;
public:
virtual double __fastcall P(void);
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TRura(void) : TPrzekladnik() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TRura(void) { }
#pragma option pop
};
class DELPHICLASS TPrzeciwposlizg;
class PASCALIMPLEMENTATION TPrzeciwposlizg : public TRura
{
typedef TRura inherited;
private:
bool Poslizg;
public:
void __fastcall SetPoslizg(bool flag);
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TPrzeciwposlizg(void) : TRura() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TPrzeciwposlizg(void) { }
#pragma option pop
};
class DELPHICLASS TRapid;
class PASCALIMPLEMENTATION TRapid : public TPrzekladnik
{
typedef TPrzekladnik inherited;
private:
bool RapidStatus;
double RapidMult;
double DN;
double DL;
public:
void __fastcall SetRapidParams(double mult, double size);
void __fastcall SetRapidStatus(bool rs);
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TRapid(void) : TPrzekladnik() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TRapid(void) { }
#pragma option pop
};
class DELPHICLASS TPrzekCiagly;
class PASCALIMPLEMENTATION TPrzekCiagly : public TPrzekladnik
{
typedef TPrzekladnik inherited;
private:
double Mult;
public:
void __fastcall SetMult(double m);
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TPrzekCiagly(void) : TPrzekladnik() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TPrzekCiagly(void) { }
#pragma option pop
};
class DELPHICLASS TPrzek_PZZ;
class PASCALIMPLEMENTATION TPrzek_PZZ : public TPrzekladnik
{
typedef TPrzekladnik inherited;
private:
double LBP;
public:
void __fastcall SetLBP(double P);
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TPrzek_PZZ(void) : TPrzekladnik() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TPrzek_PZZ(void) { }
#pragma option pop
};
class DELPHICLASS TPrzekZalamany;
class PASCALIMPLEMENTATION TPrzekZalamany : public TPrzekladnik
{
typedef TPrzekladnik inherited;
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TPrzekZalamany(void) : TPrzekladnik() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TPrzekZalamany(void) { }
#pragma option pop
};
class DELPHICLASS TPrzekED;
class PASCALIMPLEMENTATION TPrzekED : public TRura
{
typedef TRura inherited;
private:
double MaxP;
public:
void __fastcall SetP(double P);
virtual void __fastcall Update(double dt);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TPrzekED(void) : TRura() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TPrzekED(void) { }
#pragma option pop
};
class DELPHICLASS TNESt3;
class PASCALIMPLEMENTATION TNESt3 : public Hamulce::TBrake
{
typedef Hamulce::TBrake inherited;
private:
double Nozzles[11];
Hamulce::TReservoir* CntrlRes;
double BVM;
bool Zamykajacy;
bool Przys_blok;
Hamulce::TReservoir* Miedzypoj;
TPrzekladnik* Przekladniki[3];
bool RapidStatus;
bool RapidStaly;
double LoadC;
double TareM;
double LoadM;
double TareBP;
double HBG300;
double Podskok;
bool autom;
double LBP;
public:
virtual double __fastcall GetPF(double PP, double dt, double Vel);
void __fastcall EStParams(double i_crc);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetCRP(void);
void __fastcall CheckState(double BCP, double &dV1);
void __fastcall CheckReleaser(double dt);
double __fastcall CVs(double bp);
double __fastcall BVs(double BCP);
void __fastcall SetSize(int size, AnsiString params);
void __fastcall PLC(double mass);
void __fastcall SetLP(double TM, double LM, double TBP);
virtual void __fastcall ForceEmptiness(void);
void __fastcall SetLBP(double P);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TNESt3(double i_mbp, double i_bcr, double i_bcd, double i_brc
, Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : Hamulce::TBrake(i_mbp, i_bcr, i_bcd
, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TNESt3(void) { }
#pragma option pop
};
//-- var, const, procedure ---------------------------------------------------
static const Shortint dMAX = 0xa;
static const Shortint dON = 0x0;
static const Shortint dOO = 0x1;
static const Shortint dTN = 0x2;
static const Shortint dTO = 0x3;
static const Shortint dP = 0x4;
static const Shortint dSd = 0x5;
static const Shortint dSm = 0x6;
static const Shortint dPd = 0x7;
static const Shortint dPm = 0x8;
static const Shortint dPO = 0x9;
static const Shortint dPT = 0xa;
static const Shortint p_none = 0x0;
static const Shortint p_rapid = 0x1;
static const Shortint p_pp = 0x2;
static const Shortint p_al2 = 0x3;
static const Shortint p_ppz = 0x4;
static const Shortint P_ed = 0x5;
extern PACKAGE double __fastcall d2A(double d);
} /* namespace Oerlikon_est */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace Oerlikon_est;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // Oerlikon_ESt

797
McZapkie/Oerlikon_ESt.pas Normal file
View File

@@ -0,0 +1,797 @@
unit Oerlikon_ESt; {fizyka hamulcow Oerlikon ESt dla symulatora}
(*
MaSzyna EU07 - SPKS
Brakes. Oerlikon ESt.
Copyright (C) 2007-2014 Maciej Cierniak
*)
(*
(C) youBy
Co jest:
- glowny przyrzad rozrzadczy
- napelniacz zbiornika pomocniczego
- napelniacz zbiornika sterujacego
- zawor podskoku
- nibyprzyspieszacz
- tylko 16",14",12",10"
- nieprzekladnik rura
- przekladnik 1:1
- przekladniki AL2
- przeciwposlizgi
- rapid REL2
- HGB300
- inne srednice
Co brakuje:
- dobry przyspieszacz
- mozliwosc zasilania z wysokiego cisnienia ESt4
- ep: EP1 i EP2
- samoczynne ep
- PZZ dla dodatkowego
*)
interface
uses mctools,sysutils,friction,hamulce;//,klasy_ham;
CONST
dMAX=10; //dysze
dON = 0; //osobowy napelnianie (+ZP)
dOO = 1; //osobowy oproznianie
dTN = 2; //towarowy napelnianie (+ZP)
dTO = 3; //towarowy oproznianie
dP = 4; //zbiornik pomocniczy
dSd = 5; //zbiornik sterujacy
dSm = 6; //zbiornik sterujacy
dPd = 7; //duzy przelot zamykajcego
dPm = 8; //maly przelot zamykajacego
dPO = 9; //zasilanie pomocniczego O
dPT =10; //zasilanie pomocniczego T
//przekladniki
p_none = 0;
p_rapid = 1;
p_pp = 2;
p_al2 = 3;
p_ppz = 4;
P_ed = 5;
TYPE
TPrzekladnik= class(TReservoir) //przekladnik (powtarzacz)
private
public
BrakeRes: PReservoir;
Next: PReservoir;
procedure Update(dt:real); virtual;
end;
TRura= class(TPrzekladnik) //nieprzekladnik, rura laczaca
private
public
function P: real; override;
procedure Update(dt:real); override;
end;
TPrzeciwposlizg= class(TRura) //przy napelnianiu - rura, przy poslizgu - upust
private
Poslizg: boolean;
public
procedure SetPoslizg(flag: boolean);
procedure Update(dt:real); override;
end;
TRapid= class(TPrzekladnik) //przekladnik dwustopniowy
private
RapidStatus: boolean; //status rapidu
RapidMult: real; //przelozenie (w dol)
// Komora2: real;
DN,DL: real; //srednice dysz napelniania i luzowania
public
procedure SetRapidParams(mult: real; size: real);
procedure SetRapidStatus(rs: boolean);
procedure Update(dt:real); override;
end;
TPrzekCiagly= class(TPrzekladnik) //AL2
private
Mult: real;
public
procedure SetMult(m: real);
procedure Update(dt:real); override;
end;
TPrzek_PZZ= class(TPrzekladnik) //podwojny zawor zwrotny
private
LBP: real;
public
procedure SetLBP(P: real);
procedure Update(dt:real); override;
end;
TPrzekZalamany= class(TPrzekladnik) //Knicksventil
private
public
end;
TPrzekED= class(TRura) //przy napelnianiu - rura, przy hamowaniu - upust
private
MaxP: real;
public
procedure SetP(P: real);
procedure Update(dt:real); override;
end;
TNESt3= class(TBrake)
private
Nozzles: array[0..dMAX] of real; //dysze
CntrlRes: TReservoir; //zbiornik steruj¹cy
BVM: real; //przelozenie PG-CH
// ValveFlag: byte; //polozenie roznych zaworkow
Zamykajacy: boolean; //pamiec zaworka zamykajacego
// Przys_wlot: boolean; //wlot do komory przyspieszacza
Przys_blok: boolean; //blokada przyspieszacza
Miedzypoj: TReservoir; //pojemnosc posrednia (urojona) do napelniania ZP i ZS
Przekladniki: array[1..3] of TPrzekladnik;
RapidStatus: boolean;
RapidStaly: boolean;
LoadC: real;
TareM, LoadM: real; //masa proznego i pelnego
TareBP: real; //cisnienie dla proznego
HBG300: real; //zawor ograniczajacy cisnienie
Podskok: real; //podskok preznosci poczatkowej
// HPBR: real; //zasilanie ZP z wysokiego cisnienia
autom: boolean; //odluzniacz samoczynny
LBP: real; //cisnienie hamulca pomocniczego
public
function GetPF(PP, dt, Vel: real): real; override; //przeplyw miedzy komora wstepna i PG
procedure EStParams(i_crc: real); //parametry charakterystyczne dla ESt
procedure Init(PP, HPP, LPP, BP: real; BDF: byte); override;
function GetCRP: real; override;
procedure CheckState(BCP: real; var dV1: real); //glowny przyrzad rozrzadczy
procedure CheckReleaser(dt: real); //odluzniacz
function CVs(bp: real): real; //napelniacz sterujacego
function BVs(BCP: real): real; //napelniacz pomocniczego
procedure SetSize(size: integer; params: string); //ustawianie dysz (rozmiaru ZR), przekladniki
procedure PLC(mass: real); //wspolczynnik cisnienia przystawki wazacej
procedure SetLP(TM, LM, TBP: real); //parametry przystawki wazacej
procedure ForceEmptiness(); override; //wymuszenie bycia pustym
procedure SetLBP(P: real); //cisnienie z hamulca pomocniczego
end;
function d2A(d: real):real;
implementation
function d2A(d: real):real;
begin
d2A:=(d*d)*0.7854/1000;
end;
// ------ RURA ------
function TRura.P: real;
begin
P:=Next.P;
end;
procedure TRura.Update(dt: real);
begin
Next.Flow(dVol);
dVol:=0;
end;
// ------ PRZECIWPOSLIG ------
procedure TPrzeciwposlizg.SetPoslizg(flag: boolean);
begin
Poslizg:=flag;
end;
procedure TPrzeciwposlizg.Update(dt: real);
begin
if (Poslizg) then
begin
BrakeRes.Flow(dVol);
Next.Flow(PF(Next.P,0,d2A(10))*dt);
end
else
Next.Flow(dVol);
dVol:=0;
end;
// ------ PRZEKLADNIK ------
procedure TPrzekladnik.Update(dt: real);
var BCP, BVP, dV: real;
begin
BCP:=Next.P;
BVP:=BrakeRes.P;
if(BCP>P)then
dV:=-PFVd(BCP,0,d2A(10),P)*dt
else
if(BCP<P)then
dV:=PFVa(BVP,BCP,d2A(10),P)*dt
else dV:=0;
Next.Flow(dV);
if dV>0 then
BrakeRes.Flow(-dV);
end;
// ------ PRZEKLADNIK RAPID ------
procedure TRapid.SetRapidParams(mult: real; size: real);
begin
RapidMult:=mult;
RapidStatus:=false;
if (size>0.1) then //dopasowywanie srednicy przekladnika
begin
DN:=D2A(size*0.4);
DL:=D2A(size*0.4);
end
else
begin
DN:=D2A(5);
DL:=D2A(5);
end;
end;
procedure TRapid.SetRapidStatus(rs: boolean);
begin
RapidStatus:=rs;
end;
procedure TRapid.Update(dt: real);
var BCP, BVP, dV, ActMult: real;
begin
BVP:=BrakeRes.P;
BCP:=Next.P;
if(RapidStatus)then
begin
ActMult:=RapidMult;
end
else
begin
ActMult:=1;
end;
if(BCP*RapidMult>P*actMult)then
dV:=-PFVd(BCP,0,DL,P*actMult/RapidMult)*dt
else
if(BCP*RapidMult<P*ActMult)then
dV:=PFVa(BVP,BCP,DN,P*actMult/RapidMult)*dt
else dV:=0;
Next.Flow(dV);
if dV>0 then
BrakeRes.Flow(-dV);
end;
// ------ PRZEK£ADNIK CI¥G£Y ------
procedure TPrzekCiagly.SetMult(m:real);
begin
Mult:=m;
end;
procedure TPrzekCiagly.Update(dt: real);
var BCP, BVP, dV: real;
begin
BVP:=BrakeRes.P;
BCP:=Next.P;
if(BCP>P*Mult)then
dV:=-PFVd(BCP,0,d2A(8),P*Mult)*dt
else
if(BCP<P*Mult)then
dV:=PFVa(BVP,BCP,d2A(8),P*Mult)*dt
else dV:=0;
Next.Flow(dV);
if dV>0 then
BrakeRes.Flow(-dV);
end;
// ------ PRZEK£ADNIK CI¥G£Y ------
procedure TPrzek_PZZ.SetLBP(P:real);
begin
LBP:=P;
end;
procedure TPrzek_PZZ.Update(dt: real);
var BCP, BVP, dV, Pgr: real;
begin
BVP:=BrakeRes.P;
BCP:=Next.P;
Pgr:=Max0R(LBP,P);
if(BCP>Pgr)then
dV:=-PFVd(BCP,0,d2A(8),Pgr)*dt
else
if(BCP<Pgr)then
dV:=PFVa(BVP,BCP,d2A(8),Pgr)*dt
else dV:=0;
Next.Flow(dV);
if dV>0 then
BrakeRes.Flow(-dV);
end;
// ------ PRZECIWPOSLIG ------
procedure TPrzekED.SetP(P: real);
begin
MaxP:=P;
end;
procedure TPrzekED.Update(dt: real);
begin
if Next.P>MaxP then
begin
BrakeRes.Flow(dVol);
Next.Flow(PFVd(Next.P,0,d2A(10)*dt,MaxP));
end
else
Next.Flow(dVol);
dVol:=0;
end;
// ------ OERLIKON EST NA BOGATO ------
function TNESt3.GetPF(PP, dt, Vel: real): real; //przeplyw miedzy komora wstepna i PG
var dv, dv1, temp:real;
VVP, BVP, BCP, CVP, MPP, nastG: real;
i: byte;
begin
BVP:=BrakeRes.P;
VVP:=ValveRes.P;
// BCP:=BrakeCyl.P;
BCP:=Przekladniki[1].P;
CVP:=CntrlRes.P-0.0;
MPP:=Miedzypoj.P;
dV1:=0;
nastG:=(BrakeDelayFlag and bdelay_G);
//sprawdzanie stanu
CheckState(BCP, dV1);
CheckReleaser(dt);
//luzowanie
if(BrakeStatus and b_hld)=b_off then
dV:=PF(0,BCP,Nozzles[dTO]*nastG+(1-nastG)*Nozzles[dOO])*dt*(0.1+4.9*Min0R(0.2,BCP-((CVP-0.05-VVP)*BVM+0.1)))
else dV:=0;
// BrakeCyl.Flow(-dV);
Przekladniki[1].Flow(-dV);
if((BrakeStatus and b_on)=b_on)and(Przekladniki[1].P*HBG300<MaxBP)then
dV:=PF(BVP,BCP,Nozzles[dTN]*(nastG+2*Byte(BCP<Podskok))+Nozzles[dON]*(1-nastG))*dt*(0.1+4.9*Min0R(0.2,(CVP-0.05-VVP)*BVM-BCP))
else dV:=0;
// BrakeCyl.Flow(-dV);
Przekladniki[1].Flow(-dV);
BrakeRes.Flow(dV);
for i:=1 to 3 do
begin
Przekladniki[i].Update(dt);
if (Przekladniki[i] is TRapid) then
begin
RapidStatus:=(((BrakeDelayFlag and bdelay_R)=bdelay_R) and ((Abs(Vel)>70) or ((RapidStatus) and (Abs(Vel)>50)) or (RapidStaly)));
(Przekladniki[i] as TRapid).SetRapidStatus(RapidStatus);
end
else
if (Przekladniki[i] is TPrzeciwposlizg) then
(Przekladniki[i] as TPrzeciwposlizg).SetPoslizg((BrakeStatus and b_asb)=b_asb)
else
if (Przekladniki[i] is TPrzekED) then
if (Vel<-15) then
(Przekladniki[i] as TPrzekED).SetP(0)
else (Przekladniki[i] as TPrzekED).SetP(MaxBP*3)
else
if (Przekladniki[i] is TPrzekCiagly) then
(Przekladniki[i] as TPrzekCiagly).SetMult(LoadC)
else
if (Przekladniki[i] is TPrzek_PZZ) then
(Przekladniki[i] as TPrzek_PZZ).SetLBP(LBP);
end;
//przeplyw testowy miedzypojemnosci
dV:=PF(MPP,VVP,BVs(BCP))+PF(MPP,CVP,CVs(BCP));
if(MPP-0.05>BVP)then
dV:=dV+PF(MPP-0.05,BVP,Nozzles[dPT]*nastG+(1-nastG)*Nozzles[dPO]);
if MPP>VVP then dV:=dV+PF(MPP,VVP,d2A(5));
Miedzypoj.Flow(dV*dt*0.15);
//przeplyw ZS <-> PG
temp:=CVs(BCP);
dV:=PF(CVP,MPP,temp)*dt;
CntrlRes.Flow(+dV);
ValveRes.Flow(-0.02*dV);
dV1:=dV1+0.98*dV;
//przeplyw ZP <-> MPJ
if(MPP-0.05>BVP)then
dV:=PF(BVP,MPP-0.05,Nozzles[dPT]*nastG+(1-nastG)*Nozzles[dPO])*dt
else dV:=0;
BrakeRes.Flow(dV);
dV1:=dV1+dV*0.98;
ValveRes.Flow(-0.02*dV);
//przeplyw PG <-> rozdzielacz
dV:=PF(PP,VVP,0.005)*dt; //0.01
ValveRes.Flow(-dV);
ValveRes.Act;
BrakeCyl.Act;
BrakeRes.Act;
CntrlRes.Act;
Miedzypoj.Act;
Przekladniki[1].Act;
Przekladniki[2].Act;
Przekladniki[3].Act;
GetPF:=dV-dV1;
end;
procedure TNESt3.EStParams(i_crc: real); //parametry charakterystyczne dla ESt
begin
end;
procedure TNESt3.Init(PP, HPP, LPP, BP: real; BDF: byte);
begin
ValveRes.CreatePress(1*PP);
BrakeCyl.CreatePress(1*BP);
BrakeRes.CreatePress(1*PP);
CntrlRes:=TReservoir.Create;
CntrlRes.CreateCap(15);
CntrlRes.CreatePress(1*HPP);
BrakeStatus:=Byte(BP>1)*1;
Miedzypoj:=TReservoir.Create;
Miedzypoj.CreateCap(5);
Miedzypoj.CreatePress(PP);
BVM:=1/(HPP-0.05-LPP)*MaxBP;
BrakeDelayFlag:=BDF;
Zamykajacy:=false;
if not ((FM is TDisk1) or (FM is TDisk2)) then //jesli zeliwo to schodz
RapidStaly:=false
else
RapidStaly:=true;
end;
function TNESt3.GetCRP: real;
begin
GetCRP:=CntrlRes.P;
// GetCRP:=Przekladniki[1].P;
// GetCRP:=Miedzypoj.P;
end;
procedure TNESt3.CheckState(BCP: real; var dV1: real); //glowny przyrzad rozrzadczy
var VVP, BVP, CVP, MPP: real;
begin
BVP:=BrakeRes.P; //-> tu ma byc komora rozprezna
VVP:=ValveRes.P;
CVP:=CntrlRes.P;
MPP:=Miedzypoj.P;
if(BCP<0.25)and(VVP+0.08>CVP)then Przys_blok:=false;
//sprawdzanie stanu
// if ((BrakeStatus and 1)=1)and(BCP>0.25)then
if(VVP+0.01+BCP/BVM<CVP-0.05)and(Przys_blok)then
BrakeStatus:=(BrakeStatus or 3) //hamowanie stopniowe
else if(VVP-0.01+(BCP-0.1)/BVM>CVP-0.05) then
BrakeStatus:=(BrakeStatus and 252) //luzowanie
else if(VVP+BCP/BVM>CVP-0.05) then
BrakeStatus:=(BrakeStatus and 253) //zatrzymanie napelaniania
else if(VVP+(BCP-0.1)/BVM<CVP-0.05)and(BCP>0.25)then //zatrzymanie luzowania
BrakeStatus:=(BrakeStatus or 1);
if (BrakeStatus and 1)=0 then
SoundFlag:=SoundFlag or sf_CylU;
if(VVP+0.10<CVP)and(BCP<0.25)then //poczatek hamowania
if (not Przys_blok) then
begin
ValveRes.CreatePress(0.1*VVP);
SoundFlag:=SoundFlag or sf_Acc;
ValveRes.Act;
Przys_blok:=true;
end;
if(BCP>0.5)then
Zamykajacy:=true
else if(VVP-0.6<MPP) then
Zamykajacy:=false;
end;
procedure TNESt3.CheckReleaser(dt: real); //odluzniacz
var
VVP, CVP: real;
begin
VVP:=ValveRes.P;
CVP:=CntrlRes.P;
//odluzniacz automatyczny
if(BrakeStatus and b_rls=b_rls)then
begin
CntrlRes.Flow(+PF(CVP,0,0.02)*dt);
if(CVP<VVP+0.3)or(not autom)then
BrakeStatus:=BrakeStatus and 247;
end;
end;
function TNESt3.CVs(bp: real): real; //napelniacz sterujacego
var CVP, MPP: real;
begin
CVP:=CntrlRes.P;
MPP:=Miedzypoj.P;
//przeplyw ZS <-> PG
if(MPP<CVP-0.17)then
CVS:=0
else
if(MPP>CVP-0.08)then
CVs:=Nozzles[dSD]
else
CVs:=Nozzles[dSm];
end;
function TNESt3.BVs(BCP: real): real; //napelniacz pomocniczego
var CVP, MPP: real;
begin
CVP:=CntrlRes.P;
MPP:=Miedzypoj.P;
//przeplyw ZP <-> rozdzielacz
if(MPP<CVP-0.3)then
BVs:=Nozzles[dP]
else
if(BCP<0.5) then
if(Zamykajacy)then
BVs:=Nozzles[dPm] //1.25
else
BVs:=Nozzles[dPD]
else
BVs:=0;
end;
procedure TNESt3.PLC(mass: real);
begin
LoadC:=1+Byte(Mass<LoadM)*((TareBP+(MaxBP-TareBP)*(mass-TareM)/(LoadM-TareM))/MaxBP-1);
end;
procedure TNESt3.ForceEmptiness();
begin
ValveRes.CreatePress(0);
BrakeRes.CreatePress(0);
Miedzypoj.CreatePress(0);
CntrlRes.CreatePress(0);
BrakeStatus:=0;
ValveRes.Act();
BrakeRes.Act();
Miedzypoj.Act();
CntrlRes.Act();
end;
procedure TNESt3.SetLP(TM, LM, TBP: real);
begin
TareM:=TM;
LoadM:=LM;
TareBP:=TBP;
end;
procedure TNESt3.SetLBP(P: real);
begin
LBP:=P;
end;
procedure TNESt3.SetSize(size: integer; params: string); //ustawianie dysz (rozmiaru ZR)
const
dNO1l = 1.250;
dNT1l = 0.510;
dOO1l = 0.907;
dOT1l = 0.524;
var
i:integer;
begin
if Pos('ESt3',params)>0 then
begin
Podskok:=0.7;
Przekladniki[1]:=TRura.Create;
Przekladniki[3]:=TRura.Create;
end
else
begin
Podskok:=-1;
Przekladniki[1]:=TRapid.Create;
if Pos('-s216',params)>0 then
(Przekladniki[1] as TRapid).SetRapidParams(2,16)
else
(Przekladniki[1] as TRapid).SetRapidParams(2,0);
Przekladniki[3]:=TPrzeciwposlizg.Create;
if Pos('-ED',params)>0 then
begin
Przekladniki[3].Free();
(Przekladniki[1] as TRapid).SetRapidParams(2,18);
Przekladniki[3]:=TPrzekED.Create;
end;
end;
if Pos('AL2',params)>0 then
Przekladniki[2]:=TPrzekCiagly.Create
else
if Pos('PZZ',params)>0 then
Przekladniki[2]:=TPrzek_PZZ.Create
else
Przekladniki[2]:=TRura.Create;
if (Pos('3d',params)+Pos('4d',params)>0) then autom:=false else autom:=true;
if (Pos('HBG300',params)>0) then HBG300:=1 else HBG300:=0;
case size of
16:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=5.0;//5.0;
Nozzles[dOO]:=3.4;//3.4;
Nozzles[dTN]:=2.0;
Nozzles[dTO]:=1.75;
Nozzles[dP]:=3.8;
Nozzles[dPd]:=2.70;
Nozzles[dPm]:=1.25;
Nozzles[dPO]:=Nozzles[dON];
Nozzles[dPT]:=Nozzles[dTN];
end;
14:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=4.3;
Nozzles[dOO]:=2.85;
Nozzles[dTN]:=1.83;
Nozzles[dTO]:=1.57;
Nozzles[dP]:=3.4;
Nozzles[dPd]:=2.20;
Nozzles[dPm]:=1.10;
Nozzles[dPO]:=Nozzles[dON];
Nozzles[dPT]:=Nozzles[dTN];
end;
12:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=3.7;
Nozzles[dOO]:=2.50;
Nozzles[dTN]:=1.65;
Nozzles[dTO]:=1.39;
Nozzles[dP]:=2.65;
Nozzles[dPd]:=1.80;
Nozzles[dPm]:=0.85;
Nozzles[dPO]:=Nozzles[dON];
Nozzles[dPT]:=Nozzles[dTN];
end;
10:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=3.1;
Nozzles[dOO]:=2.0;
Nozzles[dTN]:=1.35;
Nozzles[dTO]:=1.13;
Nozzles[dP]:=1.6;
Nozzles[dPd]:=1.55;
Nozzles[dPm]:=0.7;
Nozzles[dPO]:=Nozzles[dON];
Nozzles[dPT]:=Nozzles[dTN];
end;
200:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=dNO1l;
Nozzles[dOO]:=dOO1l/1.15;
Nozzles[dTN]:=dNT1l;
Nozzles[dTO]:=dOT1l;
Nozzles[dP]:=7.4;
Nozzles[dPd]:=5.3;
Nozzles[dPm]:=2.5;
Nozzles[dPO]:=7.28;
Nozzles[dPT]:=2.96;
end;
375:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=dNO1l;
Nozzles[dOO]:=dOO1l/1.15;
Nozzles[dTN]:=dNT1l;
Nozzles[dTO]:=dOT1l;
Nozzles[dP]:=13.0;
Nozzles[dPd]:=9.6;
Nozzles[dPm]:=4.4;
Nozzles[dPO]:=9.92;
Nozzles[dPT]:=3.99;
end;
150:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=dNO1l;
Nozzles[dOO]:=dOO1l;
Nozzles[dTN]:=dNT1l;
Nozzles[dTO]:=dOT1l;
Nozzles[dP]:=5.8;
Nozzles[dPd]:=4.1;
Nozzles[dPm]:=1.9;
Nozzles[dPO]:=6.33;
Nozzles[dPT]:=2.58;
end;
100:
begin //dON,dOO,dTN,dTO,dP,dS
Nozzles[dON]:=dNO1l;
Nozzles[dOO]:=dOO1l;
Nozzles[dTN]:=dNT1l;
Nozzles[dTO]:=dOT1l;
Nozzles[dP]:=4.2;
Nozzles[dPd]:=2.9;
Nozzles[dPm]:=1.4;
Nozzles[dPO]:=5.19;
Nozzles[dPT]:=2.14;
end;
else
begin
Nozzles[dON]:=0;
Nozzles[dOO]:=0;
Nozzles[dTN]:=0;
Nozzles[dTO]:=0;
Nozzles[dP]:=0;
Nozzles[dPd]:=0;
Nozzles[dPm]:=0;
end;
end;
Nozzles[dSd]:=1.1;
Nozzles[dSm]:=0.9;
//przeliczanie z mm^2 na l/m
for i:=0 to dMAX do
begin
Nozzles[i]:=d2A(Nozzles[i]); //(/1000^2*pi/4*1000)
end;
for i:=1 to 3 do
begin
Przekladniki[i].BrakeRes:=@BrakeRes;
Przekladniki[i].CreateCap(i);
Przekladniki[i].CreatePress(BrakeCyl.P);
if i<3 then
Przekladniki[i].Next:=@Przekladniki[i+1]
else
Przekladniki[i].Next:=@BrakeCyl;
end
end;
end.

484
McZapkie/Unit1.pas Normal file
View File

@@ -0,0 +1,484 @@
unit Unit1;
interface
uses
ai_driver,mtable,mover,mctools,Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
Label2: TLabel;
Label3: TLabel;
Timer1: TTimer;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label9: TLabel;
Label10: TLabel;
Label11: TLabel;
Button7: TButton;
Button8: TButton;
Label12: TLabel;
Label13: TLabel;
Label14: TLabel;
Label15: TLabel;
Button9: TButton;
Button10: TButton;
Label16: TLabel;
Label17: TLabel;
Label18: TLabel;
Label19: TLabel;
Button11: TButton;
Label20: TLabel;
Label21: TLabel;
Label22: TLabel;
Label23: TLabel;
Label24: TLabel;
Label25: TLabel;
lczas: TLabel;
Label28: TLabel;
Label29: TLabel;
Label30: TLabel;
Label31: TLabel;
Label32: TLabel;
Label33: TLabel;
Label34: TLabel;
Button12: TButton;
BStart: TButton;
Label35: TLabel;
Label36: TLabel;
Label37: TLabel;
Label38: TLabel;
Button13: TButton;
Label39: TLabel;
Label40: TLabel;
Label41: TLabel;
Label42: TLabel;
Label43: TLabel;
Button14: TButton;
Button15: TButton;
Label44: TLabel;
Label45: TLabel;
Label46: TLabel;
Label47: TLabel;
BMains: TButton;
Label48: TLabel;
Label49: TLabel;
Label50: TLabel;
Panel1: TPanel;
Label1: TLabel;
OpenDialog1: TOpenDialog;
Edit1: TEdit;
GroupBox1: TGroupBox;
CheckBox1: TCheckBox;
BSInc: TButton;
BSDec: TButton;
Label51: TLabel;
Label52: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
procedure Button11Click(Sender: TObject);
procedure Button12Click(Sender: TObject);
procedure BStartClick(Sender: TObject);
procedure Button13MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button14Click(Sender: TObject);
procedure Button15Click(Sender: TObject);
procedure BMainsClick(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure BSIncClick(Sender: TObject);
procedure BSDecClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
mtno=30;
tno:integer=0;
var
Form1: TForm1;
loc:TMoverParameters;
wagony:array[1..mtno] of TMoverParameters;
mechanik: TController;
pociag: TTrainParameters;
couplerflag:byte;
l0,l0p:TLocation;
ll:array[1..mtno] of TLocation;
r0:TRotation;
rr:array[1..mtno] of TRotation;
Shape:TTrackShape; Track:TTrackParam;
ExternalVoltage:real;
ActualTime:real;
fout: text;
OK:boolean;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var typename,path:string;slashpos:byte;
begin
couplerflag:=strtoint(Edit1.Text);
if tno>0 then
wagony[tno]:=TMoverParameters.Create;
OpenDialog1.Execute;
path:='';
typename:=OpenDialog1.Filename;
repeat
slashpos:=pos('\',typename);
if slashpos>0 then
typename:=copy(typename,slashpos+1,length(typename));
until slashpos=0;
path:=copy(opendialog1.filename,1,length(opendialog1.filename)-length(typename));
typename:=Copy(typename,1,Pos('.chk',typename)-1);
if tno=0 then
begin
loc.Init(l0,r0,0,typename,'lokomotywa',0,'',1);
OK:=loc.loadchkfile(path) and loc.CheckLocomotiveParameters(Go);
if OK then
begin
Label1.Caption:=loc.TypeName;
case loc.AutoRelayType of
2: CheckBox1.Enabled:=True;
1: CheckBox1.Checked:=True;
end;
end;
end
else
begin
wagony[tno].Init(ll[tno],rr[tno],0,typename,IntToStr(tno),0,'',0);
OK:=OK and (wagony[tno].loadchkfile(path) and wagony[tno].CheckLocomotiveParameters(Go));
if OK then
begin
Label1.Caption:=Label1.Caption+' '+wagony[tno].TypeName;
if tno=1 then
ll[tno].x:=loc.Loc.x-loc.Dim.L/2-wagony[tno].Dim.L/2
else
ll[tno].x:=wagony[tno-1].Loc.x-wagony[tno-1].Dim.L/2-wagony[tno].Dim.L/2;
wagony[tno].loc:=ll[tno];
if tno=1 then
begin
OK:=OK and loc.attach(2,@wagony[1],couplerflag);
OK:=OK and wagony[1].attach(1,@loc,couplerflag);
end
else
begin
OK:=OK and wagony[tno-1].attach(2,@wagony[tno],couplerflag);
OK:=OK and wagony[tno].attach(1,@wagony[tno-1],couplerflag);
end
end;
end;
if OK then
begin
BStart.Enabled:=True;
if tno=mtno then button1.enabled:=false
else inc(tno);
Label49.Caption:='ilosc pojazdow '+inttostr(tno);
end
else
begin
Label1.Caption:=inttostr(conversionerror)+' '+inttostr(linecount);
Button1.Enabled:=False;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var iw:integer;
begin
if Timer1.Enabled then
begin
Timer1.Enabled:=False;
CloseFile(fout);
end;
mechanik.CloseLog;
mechanik.free;
loc.Free;
for iw:=1 to tno do
wagony[iw].Free;
Close;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var dl,dt:real; iw:integer;
begin
dt:=Timer1.Interval/1000;
ActualTime:=ActualTime+dt;
if l0.x>200 then Shape.R:=1000;
if l0.x>1000 then Shape.R:=-500;
if l0.x>1500 then Shape.R:=0;
if l0.x>2000 then Shape.R:=1500;
if l0.x>2200 then Shape.R:=3000;
if l0.x>2400 then Shape.R:=0;
loc.ComputeTotalForce(dt);
for iw:=1 to tno do
wagony[iw].ComputeTotalForce(dt);
dl:=loc.ComputeMovement(dt,Shape,Track,ExternalVoltage,l0,r0);
l0.x:=l0.x+dl;
for iw:=1 to tno do
begin
dl:=wagony[iw].ComputeMovement(dt,Shape,Track,ExternalVoltage,ll[iw],rr[iw]);
ll[iw].x:=ll[iw].x+dl;
end;
mechanik.UpdateSituation(dt);
l0p.x:=500; l0p.y:=2; l0.z:=0;
if (l0.x>-1) and (l0.x<5) then
loc.PutCommand('SetVelocity',60,-1,l0p);
if (l0.x>499) and (l0.x<505) then
loc.PutCommand('SetVelocity',-1,-1,l0);
l0p.x:=3600;
if (l0.x>2985) and (l0.x<3005) then
loc.PutCommand('SetVelocity',-1,0,l0p);
if (l0.x>3600) and (l0.x<3615) then
loc.PutCommand('SetVelocity',0,0,l0);
if (l0.x>3430) and (loc.Vel<0.01) and (mechanik.GetCurrentOrder=Obey_train) then
loc.PutCommand('SetVelocity',0,0,l0);
if (loc.power>0) then
begin
Label2.Caption:='I0='+r2s(Loc.Im,0)+' A';
Label3.Caption:=r2s(Loc.Ft/1000,0)+' kN';
Label13.Caption:=IntToStr(Loc.MainCtrlPos);
Label18.Caption:=IntToStr(Loc.ScndCtrlPos);
Label20.Caption:=IntToStr(Loc.MainCtrlActualPos);
Label21.Caption:=IntToStr(Loc.ScndCtrlActualPos);
end
else
for iw:=1 to tno do
if wagony[iw].power>0 then
begin
Label2.Caption:='I'+IntToStr(iw)+'='+r2s(wagony[iw].Im,0)+' A';
Label3.Caption:=r2s(wagony[iw].Ft/1000,0)+' kN';
Label13.Caption:=IntToStr(wagony[iw].MainCtrlPos);
Label18.Caption:=IntToStr(wagony[iw].ScndCtrlPos);
Label20.Caption:=IntToStr(wagony[iw].MainCtrlActualPos);
Label21.Caption:=IntToStr(wagony[iw].ScndCtrlActualPos);
end;
Label4.Caption:=r2s(l0.x,0)+' m';
Label5.Caption:=r2s(Sign(Loc.V)*Loc.Vel,0)+' km/h';
Label6.Caption:=r2s(Loc.AccS,0)+' m/ss';
Label9.Caption:=r2s(Loc.Fb/1000,0)+' kN';
Label10.Caption:=r2s(Loc.Compressor,0)+' MPa';
Label11.Caption:=r2s(Loc.PipePress,0)+' MPa';
Label12.Caption:=r2s(Loc.BrakePress,0)+' MPa';
Label14.Caption:=IntToStr(Loc.BrakeCtrlPos);
Label15.Caption:=IntToStr(Loc.LocalBrakePos);
Label16.Caption:=IntToStr(Loc.showcurrent(1));
Label17.Caption:=IntToStr(Loc.showcurrent(2));
if loc.SlippingWheels then
Label19.Caption:='Poslizg!'
else Label19.Caption:=' ';
Label22.Caption:=r2s(ll[1].x,0)+' m';
if tno>=1 then
begin
Label23.Caption:=r2s(Sign(wagony[1].V)*wagony[1].Vel,0)+' km/h';
Label24.Caption:=r2s(Distance(loc.loc,wagony[1].loc,loc.dim,wagony[1].dim),0)+' m';
end;
Label25.Caption:=r2s(loc.nrot,0)+' 1/s';
Label28.Caption:=r2s(ll[2].x,0)+' m';
if tno>=2 then
Label29.Caption:=r2s(sign(wagony[2].V)*wagony[2].Vel,0)+' km/h';
Label30.Caption:=r2s(loc.dpLocalValve/dt,0)+' MPa/s';
Label31.Caption:=r2s(loc.dpBrake/dt,0)+' MPa/s';
Label32.Caption:=r2s(loc.dpMainValve/dt,0)+' MPa/s';
Label33.Caption:=r2s(loc.dpPipe/dt,0)+' MPa/s';
if tno>0 then Label34.Caption:=r2s(wagony[tno].PipePress,0)+' MPa';
Label35.Caption:=r2s(ll[3].x,0)+' m';
if tno>0 then Label36.Caption:=r2s(sign(wagony[tno].V)*wagony[tno].Vel,0)+' km/h';
if tno>0 then Label37.Caption:=r2s(wagony[tno].couplers[1].cforce/1000,0)+' kN';
if tno>0 then Label38.Caption:=r2s(wagony[tno].brakepress,0)+' MPa';
Label39.Caption:=r2s(loc.enginePower/1000,0)+' kW';
Label40.Caption:=i2s(trunc(loc.Rventrot*60))+' /min';
Label41.Visible:=loc.SandDose;
Label42.Caption:=r2s(mechanik.accdesired,0)+' m/ss';
Label43.Caption:=r2s(mechanik.veldesired,0)+' km/h';
if tno>0 then Label44.Caption:=r2s(ll[tno].x,0)+' m';
Label45.Caption:=inttostr(loc.activedir);
Label46.Caption:=inttostr(ord(mechanik.orderlist[mechanik.orderpos]));
Label47.Caption:=inttostr(mechanik.orderpos);
Label48.Caption:=inttostr(ord(loc.mains));
{ if tno>0 then Label51.Caption:=wagony[1].CommandIn.Command;
if tno>0 then Label52.Caption:=r2s(wagony[1].CommandIn.Value1,0);
}
Label51.Caption:=loc.CommandIn.Command;
Label52.Caption:=r2s(loc.CommandIn.Value1,0);
Lczas.Caption:=r2s(actualtime,0)+' s';
writeln(fout,Actualtime,' ',{loc.v-wag.v,}loc.UnitBrakeForce,' ',loc.dpMainValve,{' ',loc.dpLocalValve,}' ',loc.accs,' ',loc.couplers[2].cforce,' ',{,l1.x}' '{,Distance(loc.loc,wagony[1].loc,loc.dim,wagony[1].dim)});
end;
procedure TForm1.FormCreate(Sender: TObject);
var iw:integer;
begin
Timer1.Enabled:=False;
tno:=0;
assignfile(fout,'log.dat');
rewrite(fout);
ActualTime:=0;
loc:=TMoverParameters.Create;
Shape.R:=0; Shape.Len:=10000; Shape.dHtrack:=0; Shape.dHrail:=0;
Track.Width:=1435; Track.friction:=0.15; Track.CategoryFlag:=1;
Track.QualityFlag:=25; Track.DamageFlag:=0;
Track.VelMax:=120;
ExternalVoltage:=3000;
l0.x:=0; l0.y:=0; l0.z:=0;
r0.rx:=0; r0.ry:=0; r0.rz:=0;
for iw:=1 to mtno do
begin
rr[iw].rx:=0; rr[iw].ry:=0; rr[iw].rz:=0;
ll[iw].x:=0; ll[iw].y:=0; ll[iw].z:=0;
end;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
loc.incbrakelevel;
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
loc.decbrakelevel;
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
loc.inclocalbrakelevel(1);
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
loc.declocalbrakelevel(1);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
loc.incmainctrl(1);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
loc.decmainctrl(1);
end;
procedure TForm1.Button9Click(Sender: TObject);
begin
loc.DirectionForward;
end;
procedure TForm1.Button10Click(Sender: TObject);
begin
loc.DirectionBackward;
end;
procedure TForm1.Button11Click(Sender: TObject);
begin
loc.FuseOn;
end;
procedure TForm1.Button12Click(Sender: TObject);
begin
Loc.AntiSlippingBrake;
end;
procedure TForm1.BStartClick(Sender: TObject);
begin
tno:=tno-1;
Button1.Enabled:=False;
Edit1.Enabled:=False;
Timer1.Enabled:=True;
mechanik:=TController.Create;
pociag:=TTrainParameters.Create;
pociag.init('Testowy Express',100);
mechanik.init(l0,r0,HumanDriver,@loc,@pociag,Aggressive);
BStart.Enabled:=False;
Button14.enabled:=True;
Button15.enabled:=True;
end;
procedure TForm1.Button13MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
loc.SandDoseOn;
end;
procedure TForm1.Button14Click(Sender: TObject);
begin
mechanik.SetVelocity(30,120);
end;
procedure TForm1.Button15Click(Sender: TObject);
begin
mechanik.AIControllFlag:=not mechanik.AIControllFlag;
if not loc.mains then
begin
mechanik.ChangeOrder(Prepare_Engine);
mechanik.JumpToNextOrder;
mechanik.ChangeOrder(Obey_train);
mechanik.JumpToNextOrder;
mechanik.ChangeOrder(Release_engine);
mechanik.JumpToFirstOrder;
mechanik.SetVelocity(60,120);
end;
end;
procedure TForm1.BMainsClick(Sender: TObject);
begin
loc.MainSwitch;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
loc.autorelayswitch;
end;
procedure TForm1.BSIncClick(Sender: TObject);
begin
loc.incscndctrl(1);
end;
procedure TForm1.BSDecClick(Sender: TObject);
begin
loc.decscndctrl(1);
end;
end.

880
McZapkie/_Mover.hpp Normal file
View File

@@ -0,0 +1,880 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) '_mover.pas' rev: 5.00
#ifndef _moverHPP
#define _moverHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <Oerlikon_ESt.hpp> // Pascal unit
#include <hamulce.hpp> // Pascal unit
#include <SysUtils.hpp> // Pascal unit
#include <mctools.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace _mover
{
//-- type declarations -------------------------------------------------------
struct TLocation
{
double X;
double Y;
double Z;
} ;
struct TRotation
{
double Rx;
double Ry;
double Rz;
} ;
struct TDimension
{
double W;
double L;
double H;
} ;
struct TCommand
{
AnsiString Command;
double Value1;
double Value2;
TLocation Location;
} ;
struct TTrackShape
{
double R;
double Len;
double dHtrack;
double dHrail;
} ;
struct TTrackParam
{
double Width;
double friction;
Byte CategoryFlag;
Byte QualityFlag;
Byte DamageFlag;
double Velmax;
} ;
struct TTractionParam
{
double TractionVoltage;
double TractionFreq;
double TractionMaxCurrent;
double TractionResistivity;
} ;
#pragma option push -b-
enum TBrakeSystem { Individual, Pneumatic, ElectroPneumatic };
#pragma option pop
#pragma option push -b-
enum TBrakeSubSystem { ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako };
#pragma option pop
#pragma option push -b-
enum TBrakeValve { NoValve, W, W_Lu_VI, W_Lu_L, W_Lu_XR, K, Kg, Kp, Kss, Kkg, Kkp, Kks, Hikg1, Hikss,
Hikp1, KE, SW, EStED, NESt3, ESt3, LSt, ESt4, ESt3AL2, EP1, EP2, M483, CV1_L_TR, CV1, CV1_R, Other
};
#pragma option pop
#pragma option push -b-
enum TBrakeHandle { NoHandle, West, FV4a, M394, M254, FVel1, FVel6, D2, Knorr, FD1, BS2, testH, St113
};
#pragma option pop
#pragma option push -b-
enum TLocalBrake { NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake };
#pragma option pop
typedef double TBrakeDelayTable[4];
struct TBrakePressure
{
double PipePressureVal;
double BrakePressureVal;
double FlowSpeedVal;
TBrakeSystem BrakeType;
} ;
typedef TBrakePressure TBrakePressureTable[13];
#pragma option push -b-
enum TEngineTypes { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine,
SteamEngine, DieselElectric };
#pragma option pop
#pragma option push -b-
enum TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower };
#pragma option pop
#pragma option push -b-
enum TFuelType { Undefined, Coal, Oil };
#pragma option pop
struct TGrateType
{
TFuelType FuelType;
double GrateSurface;
double FuelTransportSpeed;
double IgnitionTemperature;
double MaxTemperature;
} ;
struct TBoilerType
{
double BoilerVolume;
double BoilerHeatSurface;
double SuperHeaterSurface;
double MaxWaterVolume;
double MinWaterVolume;
double MaxPressure;
} ;
struct TCurrentCollector
{
int CollectorsNo;
double MinH;
double MaxH;
double CSW;
double MinV;
double MaxV;
double InsetV;
double MinPress;
double MaxPress;
} ;
#pragma option push -b-
enum TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector,
PowerCable, Heater };
#pragma option pop
struct _mover__1
{
double MaxCapacity;
TPowerSource RechargeSource;
} ;
struct _mover__2
{
TPowerType PowerTrans;
double SteamPressure;
} ;
struct _mover__3
{
TGrateType Grate;
TBoilerType Boiler;
} ;
struct TPowerParameters
{
double MaxVoltage;
double MaxCurrent;
double IntR;
TPowerSource SourceType;
union
{
struct
{
_mover__3 RHeater;
};
struct
{
_mover__2 RPowerCable;
};
struct
{
TCurrentCollector CollectorParameters;
};
struct
{
_mover__1 RAccumulator;
};
struct
{
TEngineTypes GeneratorEngine;
};
struct
{
double InputVoltage;
};
struct
{
TPowerType PowerType;
};
};
} ;
struct TScheme
{
Byte Relay;
double R;
Byte Bn;
Byte Mn;
bool AutoSwitch;
Byte ScndAct;
} ;
typedef TScheme TSchemeTable[65];
struct TDEScheme
{
double RPM;
double GenPower;
double Umax;
double Imax;
} ;
typedef TDEScheme TDESchemeTable[33];
struct TShuntScheme
{
double Umin;
double Umax;
double Pmin;
double Pmax;
} ;
typedef TShuntScheme TShuntSchemeTable[33];
struct TMPTRelay
{
double Iup;
double Idown;
} ;
typedef TMPTRelay TMPTRelayTable[8];
struct TMotorParameters
{
double mfi;
double mIsat;
double mfi0;
double fi;
double Isat;
double fi0;
bool AutoSwitch;
} ;
struct TSecuritySystem
{
Byte SystemType;
double AwareDelay;
double AwareMinSpeed;
double SoundSignalDelay;
double EmergencyBrakeDelay;
Byte Status;
double SystemTimer;
double SystemSoundCATimer;
double SystemSoundSHPTimer;
double SystemBrakeCATimer;
double SystemBrakeSHPTimer;
double SystemBrakeCATestTimer;
int VelocityAllowed;
int NextVelocityAllowed;
bool RadioStop;
} ;
struct TTransmision
{
Byte NToothM;
Byte NToothW;
double Ratio;
} ;
#pragma option push -b-
enum TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic };
#pragma option pop
class DELPHICLASS T_MoverParameters;
struct TCoupling;
class PASCALIMPLEMENTATION T_MoverParameters : public System::TObject
{
typedef System::TObject inherited;
public:
double dMoveLen;
AnsiString filename;
Byte CategoryFlag;
AnsiString TypeName;
int TrainType;
TEngineTypes EngineType;
TPowerParameters EnginePowerSource;
TPowerParameters SystemPowerSource;
TPowerParameters HeatingPowerSource;
TPowerParameters AlterHeatPowerSource;
TPowerParameters LightPowerSource;
TPowerParameters AlterLightPowerSource;
double Vmax;
double Mass;
double Power;
double Mred;
double TotalMass;
double HeatingPower;
double LightPower;
double BatteryVoltage;
bool Battery;
bool EpFuse;
bool Signalling;
bool DoorSignalling;
bool Radio;
double NominalBatteryVoltage;
TDimension Dim;
double Cx;
double Floor;
double WheelDiameter;
double WheelDiameterL;
double WheelDiameterT;
double TrackW;
double AxleInertialMoment;
AnsiString AxleArangement;
Byte NPoweredAxles;
Byte NAxles;
Byte BearingType;
double ADist;
double BDist;
Byte NBpA;
int SandCapacity;
TBrakeSystem BrakeSystem;
TBrakeSubSystem BrakeSubsystem;
TBrakeValve BrakeValve;
TBrakeHandle BrakeHandle;
TBrakeHandle BrakeLocHandle;
double MBPM;
Hamulce::TBrake* Hamulec;
Hamulce::THandle* Handle;
Hamulce::THandle* LocHandle;
Hamulce::TReservoir* Pipe;
Hamulce::TReservoir* Pipe2;
TLocalBrake LocalBrake;
TBrakePressure BrakePressureTable[13];
TBrakePressure BrakePressureActual;
Byte ASBType;
Byte TurboTest;
double MaxBrakeForce;
double MaxBrakePress[5];
double P2FTrans;
double TrackBrakeForce;
Byte BrakeMethod;
double HighPipePress;
double LowPipePress;
double DeltaPipePress;
double CntrlPipePress;
double BrakeVolume;
double BrakeVVolume;
double VeselVolume;
int BrakeCylNo;
double BrakeCylRadius;
double BrakeCylDist;
double BrakeCylMult[3];
Byte LoadFlag;
double BrakeCylSpring;
double BrakeSlckAdj;
double BrakeRigEff;
double RapidMult;
int BrakeValveSize;
AnsiString BrakeValveParams;
double Spg;
double MinCompressor;
double MaxCompressor;
double CompressorSpeed;
double BrakeDelay[4];
Byte BrakeCtrlPosNo;
Byte MainCtrlPosNo;
Byte ScndCtrlPosNo;
bool ScndInMain;
bool MBrake;
TSecuritySystem SecuritySystem;
TScheme RList[65];
int RlistSize;
TMotorParameters MotorParam[11];
TTransmision Transmision;
double NominalVoltage;
double WindingRes;
double u;
double CircuitRes;
int IminLo;
int IminHi;
int ImaxLo;
int ImaxHi;
double nmax;
double InitialCtrlDelay;
double CtrlDelay;
double CtrlDownDelay;
Byte FastSerialCircuit;
Byte AutoRelayType;
bool CoupledCtrl;
bool IsCoupled;
Byte DynamicBrakeType;
Byte RVentType;
double RVentnmax;
double RVentCutOff;
int CompressorPower;
int SmallCompressorPower;
double dizel_Mmax;
double dizel_nMmax;
double dizel_Mnmax;
double dizel_nmax;
double dizel_nominalfill;
double dizel_Mstand;
double dizel_nmax_cutoff;
double dizel_nmin;
double dizel_minVelfullengage;
double dizel_AIM;
double dizel_engageDia;
double dizel_engageMaxForce;
double dizel_engagefriction;
double AnPos;
bool AnalogCtrl;
bool AnMainCtrl;
bool ShuntModeAllow;
bool ShuntMode;
bool Flat;
double Vhyp;
TDEScheme DElist[33];
double Vadd;
TMPTRelay MPTRelay[8];
Byte RelayType;
TShuntScheme SST[33];
double PowerCorRatio;
double Ftmax;
double eimc[21];
int MaxLoad;
AnsiString LoadAccepted;
AnsiString LoadQuantity;
double OverLoadFactor;
double LoadSpeed;
double UnLoadSpeed;
Byte DoorOpenCtrl;
Byte DoorCloseCtrl;
double DoorStayOpen;
bool DoorClosureWarning;
double DoorOpenSpeed;
double DoorCloseSpeed;
double DoorMaxShiftL;
double DoorMaxShiftR;
Byte DoorOpenMethod;
bool ScndS;
TLocation Loc;
TRotation Rot;
AnsiString Name;
TCoupling Couplers[2];
double HVCouplers[2][2];
int ScanCounter;
bool EventFlag;
Byte SoundFlag;
double DistCounter;
double V;
double Vel;
double AccS;
double AccN;
double AccV;
double nrot;
double EnginePower;
double dL;
double Fb;
double Ff;
double FTrain;
double FStand;
double FTotal;
double UnitBrakeForce;
double Ntotal;
bool SlippingWheels;
bool SandDose;
double Sand;
double BrakeSlippingTimer;
double dpBrake;
double dpPipe;
double dpMainValve;
double dpLocalValve;
double ScndPipePress;
double BrakePress;
double LocBrakePress;
double PipeBrakePress;
double PipePress;
double EqvtPipePress;
double Volume;
double CompressedVolume;
double PantVolume;
double Compressor;
bool CompressorFlag;
bool PantCompFlag;
bool CompressorAllow;
bool ConverterFlag;
bool ConverterAllow;
int BrakeCtrlPos;
double BrakeCtrlPosR;
double BrakeCtrlPos2;
Byte LocalBrakePos;
Byte ManualBrakePos;
double LocalBrakePosA;
Byte BrakeStatus;
bool EmergencyBrakeFlag;
Byte BrakeDelayFlag;
Byte BrakeDelays;
bool DynamicBrakeFlag;
double LimPipePress;
double ActFlowSpeed;
Byte DamageFlag;
Byte DerailReason;
TCommand CommandIn;
AnsiString CommandOut;
AnsiString CommandLast;
double ValueOut;
TTrackShape RunningShape;
TTrackParam RunningTrack;
double OffsetTrackH;
double OffsetTrackV;
bool Mains;
Byte MainCtrlPos;
Byte ScndCtrlPos;
int ActiveDir;
int CabNo;
int DirAbsolute;
int ActiveCab;
double LastSwitchingTime;
bool DepartureSignal;
bool InsideConsist;
TTractionParam RunningTraction;
double enrot;
double Im;
double Itot;
double IHeating;
double ITraction;
double TotalCurrent;
double Mm;
double Mw;
double Fw;
double Ft;
int Imin;
int Imax;
double Voltage;
Byte MainCtrlActualPos;
Byte ScndCtrlActualPos;
bool DelayCtrlFlag;
double LastRelayTime;
bool AutoRelayFlag;
bool FuseFlag;
bool ConvOvldFlag;
bool StLinFlag;
bool ResistorsFlag;
double RventRot;
bool UnBrake;
double PantPress;
bool s_CAtestebrake;
double dizel_fill;
double dizel_engagestate;
double dizel_engage;
double dizel_automaticgearstatus;
bool dizel_enginestart;
double dizel_engagedeltaomega;
double eimv[21];
double PulseForce;
double PulseForceTimer;
int PulseForceCount;
double eAngle;
int Load;
AnsiString LoadType;
Byte LoadStatus;
double LastLoadChangeTime;
bool DoorBlocked;
bool DoorLeftOpened;
bool DoorRightOpened;
bool PantFrontUp;
bool PantRearUp;
bool PantFrontSP;
bool PantRearSP;
int PantFrontStart;
int PantRearStart;
double PantFrontVolt;
double PantRearVolt;
AnsiString PantSwitchType;
AnsiString ConvSwitchType;
bool Heating;
int DoubleTr;
bool PhysicActivation;
double FrictConst1;
double FrictConst2s;
double FrictConst2d;
double TotalMassxg;
double __fastcall GetTrainsetVoltage(void);
bool __fastcall Physic_ReActivation(void);
double __fastcall LocalBrakeRatio(void);
double __fastcall ManualBrakeRatio(void);
double __fastcall PipeRatio(void);
double __fastcall RealPipeRatio(void);
double __fastcall BrakeVP(void);
bool __fastcall DynamicBrakeSwitch(bool Switch);
bool __fastcall SendCtrlBroadcast(AnsiString CtrlCommand, double ctrlvalue);
bool __fastcall SendCtrlToNext(AnsiString CtrlCommand, double ctrlvalue, double dir);
bool __fastcall CabActivisation(void);
bool __fastcall CabDeactivisation(void);
bool __fastcall IncMainCtrl(int CtrlSpeed);
bool __fastcall DecMainCtrl(int CtrlSpeed);
bool __fastcall IncScndCtrl(int CtrlSpeed);
bool __fastcall DecScndCtrl(int CtrlSpeed);
bool __fastcall AddPulseForce(int Multipler);
bool __fastcall SandDoseOn(void);
bool __fastcall SecuritySystemReset(void);
void __fastcall SecuritySystemCheck(double dt);
bool __fastcall BatterySwitch(bool State);
bool __fastcall EpFuseSwitch(bool State);
bool __fastcall IncBrakeLevelOld(void);
bool __fastcall DecBrakeLevelOld(void);
bool __fastcall IncLocalBrakeLevel(Byte CtrlSpeed);
bool __fastcall DecLocalBrakeLevel(Byte CtrlSpeed);
bool __fastcall IncLocalBrakeLevelFAST(void);
bool __fastcall DecLocalBrakeLevelFAST(void);
bool __fastcall IncManualBrakeLevel(Byte CtrlSpeed);
bool __fastcall DecManualBrakeLevel(Byte CtrlSpeed);
bool __fastcall EmergencyBrakeSwitch(bool Switch);
bool __fastcall AntiSlippingBrake(void);
bool __fastcall BrakeReleaser(Byte state);
bool __fastcall SwitchEPBrake(Byte state);
bool __fastcall AntiSlippingButton(void);
bool __fastcall IncBrakePress(double &brake, double PressLimit, double dp);
bool __fastcall DecBrakePress(double &brake, double PressLimit, double dp);
bool __fastcall BrakeDelaySwitch(Byte BDS);
bool __fastcall IncBrakeMult(void);
bool __fastcall DecBrakeMult(void);
void __fastcall UpdateBrakePressure(double dt);
void __fastcall UpdatePipePressure(double dt);
void __fastcall CompressorCheck(double dt);
void __fastcall UpdateScndPipePressure(double dt);
double __fastcall GetDVc(double dt);
void __fastcall ComputeConstans(void);
double __fastcall ComputeMass(void);
double __fastcall Adhesive(double staticfriction);
double __fastcall TractionForce(double dt);
double __fastcall FrictionForce(double R, Byte TDamage);
double __fastcall BrakeForce(const TTrackParam &Track);
double __fastcall CouplerForce(Byte CouplerN, double dt);
void __fastcall CollisionDetect(Byte CouplerN, double dt);
double __fastcall ComputeRotatingWheel(double WForce, double dt, double n);
bool __fastcall SetInternalCommand(AnsiString NewCommand, double NewValue1, double NewValue2);
double __fastcall GetExternalCommand(AnsiString &Command);
bool __fastcall RunCommand(AnsiString command, double CValue1, double CValue2);
bool __fastcall RunInternalCommand(void);
void __fastcall PutCommand(AnsiString NewCommand, double NewValue1, double NewValue2, const TLocation
&NewLocation);
bool __fastcall DirectionBackward(void);
bool __fastcall MainSwitch(bool State);
bool __fastcall ConverterSwitch(bool State);
bool __fastcall CompressorSwitch(bool State);
bool __fastcall FuseOn(void);
bool __fastcall FuseFlagCheck(void);
void __fastcall FuseOff(void);
int __fastcall ShowCurrent(Byte AmpN);
double __fastcall v2n(void);
double __fastcall current(double n, double U);
double __fastcall Momentum(double I);
double __fastcall MomentumF(double I, double Iw, Byte SCP);
bool __fastcall CutOffEngine(void);
bool __fastcall MaxCurrentSwitch(bool State);
bool __fastcall ResistorsFlagCheck(void);
bool __fastcall MinCurrentSwitch(bool State);
bool __fastcall AutoRelaySwitch(bool State);
bool __fastcall AutoRelayCheck(void);
bool __fastcall dizel_EngageSwitch(double state);
bool __fastcall dizel_EngageChange(double dt);
bool __fastcall dizel_AutoGearCheck(void);
double __fastcall dizel_fillcheck(Byte mcp);
double __fastcall dizel_Momentum(double dizel_fill, double n, double dt);
bool __fastcall dizel_Update(double dt);
bool __fastcall LoadingDone(double LSpeed, AnsiString LoadInit);
void __fastcall ComputeTotalForce(double dt, double dt1, bool FullVer);
double __fastcall ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track
, TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot);
double __fastcall FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const
TLocation &NewLoc, TRotation &NewRot);
bool __fastcall ChangeOffsetH(double DeltaOffset);
__fastcall T_MoverParameters(double VelInitial, AnsiString TypeNameInit, AnsiString NameInit, int LoadInitial
, AnsiString LoadTypeInitial, int Cab);
bool __fastcall LoadChkFile(AnsiString chkpath);
bool __fastcall CheckLocomotiveParameters(bool ReadyFlag, int Dir);
AnsiString __fastcall EngineDescription(int what);
bool __fastcall DoorLeft(bool State);
bool __fastcall DoorRight(bool State);
bool __fastcall DoorBlockedFlag(void);
bool __fastcall PantFront(bool State);
bool __fastcall PantRear(bool State);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall T_MoverParameters(void) : System::TObject() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~T_MoverParameters(void) { }
#pragma option pop
};
struct TCoupling
{
double SpringKB;
double SpringKC;
double beta;
double DmaxB;
double FmaxB;
double DmaxC;
double FmaxC;
TCouplerType CouplerType;
Byte CouplingFlag;
int AllowedFlag;
bool Render;
double CoupleDist;
T_MoverParameters* Connected;
Byte ConnectedNr;
double CForce;
double Dist;
bool CheckCollision;
} ;
//-- var, const, procedure ---------------------------------------------------
static const bool Go = true;
static const bool Hold = false;
static const Shortint ResArraySize = 0x40;
static const Shortint MotorParametersArraySize = 0xa;
static const Shortint maxcc = 0x4;
static const Shortint LocalBrakePosNo = 0xa;
static const Shortint MainBrakeMaxPos = 0xa;
static const Shortint ManualBrakePosNo = 0x14;
static const Shortint dtrack_railwear = 0x2;
static const Shortint dtrack_freerail = 0x4;
static const Shortint dtrack_thinrail = 0x8;
static const Shortint dtrack_railbend = 0x10;
static const Shortint dtrack_plants = 0x20;
static const Shortint dtrack_nomove = 0x40;
static const Byte dtrack_norail = 0x80;
static const Shortint dtrain_thinwheel = 0x1;
static const Shortint dtrain_loadshift = 0x1;
static const Shortint dtrain_wheelwear = 0x2;
static const Shortint dtrain_bearing = 0x4;
static const Shortint dtrain_coupling = 0x8;
static const Shortint dtrain_ventilator = 0x10;
static const Shortint dtrain_loaddamage = 0x10;
static const Shortint dtrain_engine = 0x20;
static const Shortint dtrain_loaddestroyed = 0x20;
static const Shortint dtrain_axle = 0x40;
static const Byte dtrain_out = 0x80;
#define p_elengproblem (1.000000E-02)
#define p_elengdamage (1.000000E-01)
#define p_coupldmg (2.000000E-02)
#define p_derail (1.000000E-03)
#define p_accn (1.000000E-01)
#define p_slippdmg (1.000000E-03)
static const Shortint ctrain_virtual = 0x0;
static const Shortint ctrain_coupler = 0x1;
static const Shortint ctrain_pneumatic = 0x2;
static const Shortint ctrain_controll = 0x4;
static const Shortint ctrain_power = 0x8;
static const Shortint ctrain_passenger = 0x10;
static const Shortint ctrain_scndpneumatic = 0x20;
static const Shortint ctrain_heating = 0x40;
static const Byte ctrain_depot = 0x80;
static const Shortint dbrake_none = 0x0;
static const Shortint dbrake_passive = 0x1;
static const Shortint dbrake_switch = 0x2;
static const Shortint dbrake_reversal = 0x4;
static const Shortint dbrake_automatic = 0x8;
static const Shortint s_waiting = 0x1;
static const Shortint s_aware = 0x2;
static const Shortint s_active = 0x4;
static const Shortint s_CAalarm = 0x8;
static const Shortint s_SHPalarm = 0x10;
static const Shortint s_CAebrake = 0x20;
static const Shortint s_SHPebrake = 0x40;
static const Byte s_CAtest = 0x80;
static const Shortint sound_none = 0x0;
static const Shortint sound_loud = 0x1;
static const Shortint sound_couplerstretch = 0x2;
static const Shortint sound_bufferclamp = 0x4;
static const Shortint sound_bufferbump = 0x8;
static const Shortint sound_relay = 0x10;
static const Shortint sound_manyrelay = 0x20;
static const Shortint sound_brakeacc = 0x40;
extern PACKAGE bool PhysicActivationFlag;
static const Shortint dt_Default = 0x0;
static const Shortint dt_EZT = 0x1;
static const Shortint dt_ET41 = 0x2;
static const Shortint dt_ET42 = 0x4;
static const Shortint dt_PseudoDiesel = 0x8;
static const Shortint dt_ET22 = 0x10;
static const Shortint dt_SN61 = 0x20;
static const Shortint dt_EP05 = 0x40;
static const Byte dt_ET40 = 0x80;
static const Word dt_181 = 0x100;
static const Shortint eimc_s_dfic = 0x0;
static const Shortint eimc_s_dfmax = 0x1;
static const Shortint eimc_s_p = 0x2;
static const Shortint eimc_s_cfu = 0x3;
static const Shortint eimc_s_cim = 0x4;
static const Shortint eimc_s_icif = 0x5;
static const Shortint eimc_f_Uzmax = 0x7;
static const Shortint eimc_f_Uzh = 0x8;
static const Shortint eimc_f_DU = 0x9;
static const Shortint eimc_f_I0 = 0xa;
static const Shortint eimc_f_cfu = 0xb;
static const Shortint eimc_p_F0 = 0xd;
static const Shortint eimc_p_a1 = 0xe;
static const Shortint eimc_p_Pmax = 0xf;
static const Shortint eimc_p_Fh = 0x10;
static const Shortint eimc_p_Ph = 0x11;
static const Shortint eimc_p_Vh0 = 0x12;
static const Shortint eimc_p_Vh1 = 0x13;
static const Shortint eimc_p_Imax = 0x14;
static const Shortint eimv_FMAXMAX = 0x0;
static const Shortint eimv_Fmax = 0x1;
static const Shortint eimv_ks = 0x2;
static const Shortint eimv_df = 0x3;
static const Shortint eimv_fp = 0x4;
static const Shortint eimv_U = 0x5;
static const Shortint eimv_pole = 0x6;
static const Shortint eimv_Ic = 0x7;
static const Shortint eimv_If = 0x8;
static const Shortint eimv_M = 0x9;
static const Shortint eimv_Fr = 0xa;
static const Shortint eimv_Ipoj = 0xb;
static const Shortint eimv_Pm = 0xc;
static const Shortint eimv_Pe = 0xd;
static const Shortint eimv_eta = 0xe;
static const Shortint eimv_fkr = 0xf;
static const Shortint eimv_Uzsmax = 0x10;
static const Shortint eimv_Pmax = 0x11;
static const Shortint eimv_Fzad = 0x12;
static const Shortint eimv_Imax = 0x13;
extern PACKAGE double __fastcall Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension
&Dim1, const TDimension &Dim2);
} /* namespace _mover */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace _mover;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // _mover

7380
McZapkie/_mover.pas Normal file

File diff suppressed because it is too large Load Diff

232
McZapkie/friction.hpp Normal file
View File

@@ -0,0 +1,232 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) 'friction.pas' rev: 5.00
#ifndef frictionHPP
#define frictionHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <SysUtils.hpp> // Pascal unit
#include <mctools.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace Friction
{
//-- type declarations -------------------------------------------------------
class DELPHICLASS TFricMat;
class PASCALIMPLEMENTATION TFricMat : public System::TObject
{
typedef System::TObject inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFricMat(void) : System::TObject() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFricMat(void) { }
#pragma option pop
};
class DELPHICLASS TP10Bg;
class PASCALIMPLEMENTATION TP10Bg : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TP10Bg(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TP10Bg(void) { }
#pragma option pop
};
class DELPHICLASS TP10Bgu;
class PASCALIMPLEMENTATION TP10Bgu : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TP10Bgu(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TP10Bgu(void) { }
#pragma option pop
};
class DELPHICLASS TP10yBg;
class PASCALIMPLEMENTATION TP10yBg : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TP10yBg(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TP10yBg(void) { }
#pragma option pop
};
class DELPHICLASS TP10yBgu;
class PASCALIMPLEMENTATION TP10yBgu : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TP10yBgu(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TP10yBgu(void) { }
#pragma option pop
};
class DELPHICLASS TP10;
class PASCALIMPLEMENTATION TP10 : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TP10(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TP10(void) { }
#pragma option pop
};
class DELPHICLASS TFR513;
class PASCALIMPLEMENTATION TFR513 : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFR513(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFR513(void) { }
#pragma option pop
};
class DELPHICLASS TFR510;
class PASCALIMPLEMENTATION TFR510 : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFR510(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFR510(void) { }
#pragma option pop
};
class DELPHICLASS TCosid;
class PASCALIMPLEMENTATION TCosid : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TCosid(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TCosid(void) { }
#pragma option pop
};
class DELPHICLASS TDisk1;
class PASCALIMPLEMENTATION TDisk1 : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TDisk1(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TDisk1(void) { }
#pragma option pop
};
class DELPHICLASS TDisk2;
class PASCALIMPLEMENTATION TDisk2 : public TFricMat
{
typedef TFricMat inherited;
public:
virtual double __fastcall GetFC(double N, double Vel);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TDisk2(void) : TFricMat() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TDisk2(void) { }
#pragma option pop
};
//-- var, const, procedure ---------------------------------------------------
} /* namespace Friction */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace Friction;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // friction

174
McZapkie/friction.pas Normal file
View File

@@ -0,0 +1,174 @@
unit friction; {wspolczynnik tarcia roznych materialow}
(*
MaSzyna EU07 - SPKS
Friction coefficient.
Copyright (C) 2007-2013 Maciej Cierniak
*)
(*
(C) youBy
Co brakuje:
- hamulce tarczowe
- kompozyty
*)
(*
Zrobione:
1) zadeklarowane niektore typy
2) wzor jubaja na tarcie wstawek Bg i Bgu z zeliwa P10
3) hamulec tarczowy marki 152A ;)
*)
interface
//uses hamulce;
uses mctools,sysutils;
TYPE
TFricMat = class
public
function GetFC(N, Vel: real): real; virtual;
end;
TP10Bg = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TP10Bgu = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TP10yBg = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TP10yBgu = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TP10 = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TFR513 = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TFR510 = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TCosid = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TDisk1 = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
TDisk2 = class(TFricMat)
public
function GetFC(N, Vel: real): real; override;
end;
implementation
function TFricMat.GetFC(N, Vel: real): real;
begin
GetFC:=1;
end;
function TP10Bg.GetFC(N, Vel: real): real;
begin
// GetFC:=0.60*((1.6*N+100)/(8.0*N+100))*((Vel+100)/(5*Vel+100))*(1.0032-0.0007*N-0.0001*N*N);
// GetFC:=47/(2*Vel+100)*(2.145-0.0538*N+0.00074*N*N-0.00000536*N*N*N)/2.145;
// GetFC:=46/(2*Vel+100)*(11.33-0.105*N)/(11.33+0.179*N);
// GetFC:=49/(2*Vel+100)*(13.08-0.083*N)/(12.94+0.285*N);
//if Vel<20 then Vel:=20;
// Vel:= Vel-20;
// GetFC:=0.52*((1*Vel+100)/(5.0*Vel+100))*(13.08-0.083*N)/(12.94+0.285*N);
// GetFC:=Min0R(0.67*(1*(277-2.66*Vel)/(100+2.1*Vel)+0.23*(-686+8.27*Vel)/(100+1.16*Vel))*(13.08-0.083*N)/(12.94+0.285*N),0.4);
GetFC:=exp(-0.022*N)*(0.19-0.095*exp(-Vel/25.7))+0.384*exp(-Vel/25.7)-0.028;
end;
function TP10Bgu.GetFC(N, Vel: real): real;
begin
// GetFC:=0.60*((1.6*N+100)/(8.0*N+100))*((Vel+100)/(5*Vel+100));
// GetFC:=47/(2*Vel+100)*(2.137-0.0514*N+0.000832*N*N-0.00000604*N*N*N)/2.137;
// GetFC:=0.49*100/(2*Vel+100)*(11.33-0.013*N)/(11.33+0.280*N);
// GetFC:=0.52*((Vel+100)/(5.0*Vel+100))*(11.33-0.013*N)/(11.33+0.280*N);
//if Vel<20 then Vel:=20;
// Vel:= Vel-20;
// GetFC:=0.52*((0.0*Vel+120)/(5*Vel+100))*(11.33-0.013*N)/(11.33+0.280*N);
// GetFC:=0.49*100/(3*Vel+100)*(11.33-0.013*N)/(11.33+0.280*N);
// GetFC:=Min0R(0.67*(1*(277-2.66*Vel)/(100+2.1*Vel)+0.23*(-686+8.27*Vel)/(100+1.16*Vel))*(11.33-0.013*N)/(11.33+0.280*N),0.4);
GetFC:=exp(-0.017*N)*(0.18-0.09*exp(-Vel/25.7))+0.381*exp(-Vel/25.7)-0.022;//0.05*exp(-0.2*N);
end;
function TP10yBg.GetFC(N, Vel: real): real;
var A,C,u0, V0: real;
begin
A:=2.135*exp(-0.03726*N)-0.5;
C:=0.353-A*0.029;
u0:=0.41-C;
V0:=25.7+20*A;
GetFC:=(u0+C*exp(-Vel/V0));
end;
function TP10yBgu.GetFC(N, Vel: real): real;
var A,C,u0, V0: real;
begin
A:=1.68*exp(-0.02735*N)-0.5;
C:=0.353-A*0.044;
u0:=0.41-C;
V0:=25.7+21*A;
GetFC:=(u0+C*exp(-Vel/V0));
end;
function TP10.GetFC(N, Vel: real): real;
begin
GetFC:=0.60*((1.6*N+100)/(8.0*N+100))*((Vel+100)/(5*Vel+100));
// GetFC:=43/(2*Vel+100)*(2.145-0.0538*N+0.00074*N*N-0.00000536*N*N*N)/2.145
end;
function TFR513.GetFC(N, Vel: real): real;
begin
GetFC:=0.3-Vel*0.00081;
// GetFC:=43/(2*Vel+100)*(2.145-0.0538*N+0.00074*N*N-0.00000536*N*N*N)/2.145
end;
function TCosid.GetFC(N, Vel: real): real;
begin
GetFC:=0.27;
end;
function TDisk1.GetFC(N, Vel: real): real;
begin
GetFC:=0.2375+0.000885*N-0.000345*N*N;
end;
function TDisk2.GetFC(N, Vel: real): real;
begin
GetFC:=0.27;
end;
function TFR510.GetFC(N, Vel: real): real;
begin
GetFC:=0.15;
end;
end.

841
McZapkie/hamulce.hpp Normal file
View File

@@ -0,0 +1,841 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) 'hamulce.pas' rev: 5.00
#ifndef hamulceHPP
#define hamulceHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <friction.hpp> // Pascal unit
#include <SysUtils.hpp> // Pascal unit
#include <mctools.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace Hamulce
{
//-- type declarations -------------------------------------------------------
class DELPHICLASS TReservoir;
class PASCALIMPLEMENTATION TReservoir : public System::TObject
{
typedef System::TObject inherited;
protected:
double Cap;
double Vol;
double dVol;
public:
__fastcall TReservoir(void);
void __fastcall CreateCap(double Capacity);
void __fastcall CreatePress(double Press);
virtual double __fastcall pa(void);
virtual double __fastcall P(void);
void __fastcall Flow(double dv);
void __fastcall Act(void);
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TReservoir(void) { }
#pragma option pop
};
typedef TReservoir* *PReservoir;
class DELPHICLASS TBrakeCyl;
class PASCALIMPLEMENTATION TBrakeCyl : public TReservoir
{
typedef TReservoir inherited;
public:
virtual double __fastcall pa(void);
virtual double __fastcall P(void);
public:
#pragma option push -w-inl
/* TReservoir.Create */ inline __fastcall TBrakeCyl(void) : TReservoir() { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TBrakeCyl(void) { }
#pragma option pop
};
class DELPHICLASS TBrake;
class PASCALIMPLEMENTATION TBrake : public System::TObject
{
typedef System::TObject inherited;
protected:
TReservoir* BrakeCyl;
TReservoir* BrakeRes;
TReservoir* ValveRes;
Byte BCN;
double BCM;
double BCA;
Byte BrakeDelays;
Byte BrakeDelayFlag;
Friction::TFricMat* FM;
double MaxBP;
Byte BA;
Byte NBpA;
double SizeBR;
double SizeBC;
bool DCV;
double ASBP;
Byte BrakeStatus;
Byte SoundFlag;
public:
__fastcall TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, Byte i_bcn, Byte i_BD, Byte
i_mat, Byte i_ba, Byte i_nbpa);
virtual double __fastcall GetFC(double Vel, double N);
virtual double __fastcall GetPF(double PP, double dt, double Vel);
double __fastcall GetBCF(void);
virtual double __fastcall GetHPFlow(double HP, double dt);
virtual double __fastcall GetBCP(void);
double __fastcall GetBRP(void);
double __fastcall GetVRP(void);
virtual double __fastcall GetCRP(void);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
bool __fastcall SetBDF(Byte nBDF);
void __fastcall Releaser(Byte state);
virtual void __fastcall SetEPS(double nEPS);
void __fastcall ASB(Byte state);
Byte __fastcall GetStatus(void);
void __fastcall SetASBP(double press);
virtual void __fastcall ForceEmptiness(void);
Byte __fastcall GetSoundFlag(void);
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TBrake(void) { }
#pragma option pop
};
class DELPHICLASS TWest;
class PASCALIMPLEMENTATION TWest : public TBrake
{
typedef TBrake inherited;
private:
double LBP;
double dVP;
double EPS;
double TareM;
double LoadM;
double TareBP;
double LoadC;
public:
void __fastcall SetLBP(double P);
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetHPFlow(double HP, double dt);
void __fastcall PLC(double mass);
virtual void __fastcall SetEPS(double nEPS);
void __fastcall SetLP(double TM, double LM, double TBP);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TWest(double i_mbp, double i_bcr, double i_bcd, double i_brc,
Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TWest(void) { }
#pragma option pop
};
class DELPHICLASS TESt;
class PASCALIMPLEMENTATION TESt : public TBrake
{
typedef TBrake inherited;
private:
TReservoir* CntrlRes;
double BVM;
public:
virtual double __fastcall GetPF(double PP, double dt, double Vel);
void __fastcall EStParams(double i_crc);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetCRP(void);
void __fastcall CheckState(double BCP, double &dV1);
void __fastcall CheckReleaser(double dt);
double __fastcall CVs(double bp);
double __fastcall BVs(double BCP);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TESt(double i_mbp, double i_bcr, double i_bcd, double i_brc,
Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TESt(void) { }
#pragma option pop
};
class DELPHICLASS TESt3;
class PASCALIMPLEMENTATION TESt3 : public TESt
{
typedef TESt inherited;
private:
double CylFlowSpeed[2][2];
public:
virtual double __fastcall GetPF(double PP, double dt, double Vel);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TESt3(double i_mbp, double i_bcr, double i_bcd, double i_brc,
Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TESt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TESt3(void) { }
#pragma option pop
};
class DELPHICLASS TESt3AL2;
class PASCALIMPLEMENTATION TESt3AL2 : public TESt3
{
typedef TESt3 inherited;
private:
double TareM;
double LoadM;
double TareBP;
double LoadC;
public:
TReservoir* ImplsRes;
virtual double __fastcall GetPF(double PP, double dt, double Vel);
void __fastcall PLC(double mass);
void __fastcall SetLP(double TM, double LM, double TBP);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TESt3AL2(double i_mbp, double i_bcr, double i_bcd, double i_brc
, Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TESt3(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TESt3AL2(void) { }
#pragma option pop
};
class DELPHICLASS TESt4R;
class PASCALIMPLEMENTATION TESt4R : public TESt
{
typedef TESt inherited;
private:
bool RapidStatus;
double RapidTemp;
public:
TReservoir* ImplsRes;
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TESt4R(double i_mbp, double i_bcr, double i_bcd, double i_brc
, Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TESt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TESt4R(void) { }
#pragma option pop
};
class DELPHICLASS TLSt;
class PASCALIMPLEMENTATION TLSt : public TESt4R
{
typedef TESt4R inherited;
private:
double CylFlowSpeed[2][2];
double LBP;
double RM;
double EDFlag;
public:
void __fastcall SetLBP(double P);
void __fastcall SetRM(double RMR);
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual double __fastcall GetHPFlow(double HP, double dt);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetEDBCP(void);
void __fastcall SetED(double EDstate);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TLSt(double i_mbp, double i_bcr, double i_bcd, double i_brc,
Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TESt4R(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TLSt(void) { }
#pragma option pop
};
class DELPHICLASS TEStED;
class PASCALIMPLEMENTATION TEStED : public TLSt
{
typedef TLSt inherited;
private:
double Nozzles[11];
bool Zamykajacy;
bool Przys_blok;
TReservoir* Miedzypoj;
public:
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual double __fastcall GetEDBCP(void);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TEStED(double i_mbp, double i_bcr, double i_bcd, double i_brc
, Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TLSt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TEStED(void) { }
#pragma option pop
};
class DELPHICLASS TEStEP2;
class PASCALIMPLEMENTATION TEStEP2 : public TLSt
{
typedef TLSt inherited;
private:
double TareM;
double LoadM;
double TareBP;
double LoadC;
double EPS;
public:
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
void __fastcall PLC(double mass);
virtual void __fastcall SetEPS(double nEPS);
void __fastcall SetLP(double TM, double LM, double TBP);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TEStEP2(double i_mbp, double i_bcr, double i_bcd, double i_brc
, Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TLSt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TEStEP2(void) { }
#pragma option pop
};
class DELPHICLASS TCV1;
class PASCALIMPLEMENTATION TCV1 : public TBrake
{
typedef TBrake inherited;
private:
TReservoir* CntrlRes;
double BVM;
public:
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetCRP(void);
void __fastcall CheckState(double BCP, double &dV1);
double __fastcall CVs(double bp);
double __fastcall BVs(double BCP);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TCV1(double i_mbp, double i_bcr, double i_bcd, double i_brc,
Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TCV1(void) { }
#pragma option pop
};
class DELPHICLASS TCV1R;
class PASCALIMPLEMENTATION TCV1R : public TCV1
{
typedef TCV1 inherited;
private:
TReservoir* ImplsRes;
bool RapidStatus;
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TCV1R(double i_mbp, double i_bcr, double i_bcd, double i_brc,
Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TCV1(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TCV1R(void) { }
#pragma option pop
};
class DELPHICLASS TCV1L_TR;
class PASCALIMPLEMENTATION TCV1L_TR : public TCV1
{
typedef TCV1 inherited;
private:
TReservoir* ImplsRes;
double LBP;
public:
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
void __fastcall SetLBP(double P);
virtual double __fastcall GetHPFlow(double HP, double dt);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TCV1L_TR(double i_mbp, double i_bcr, double i_bcd, double i_brc
, Byte i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TCV1(i_mbp, i_bcr, i_bcd, i_brc, i_bcn
, i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TCV1L_TR(void) { }
#pragma option pop
};
class DELPHICLASS TKE;
class PASCALIMPLEMENTATION TKE : public TBrake
{
typedef TBrake inherited;
private:
bool RapidStatus;
TReservoir* ImplsRes;
TReservoir* CntrlRes;
TReservoir* Brak2Res;
double BVM;
double TareM;
double LoadM;
double TareBP;
double LoadC;
double RM;
double LBP;
public:
void __fastcall SetRM(double RMR);
virtual double __fastcall GetPF(double PP, double dt, double Vel);
virtual void __fastcall Init(double PP, double HPP, double LPP, double BP, Byte BDF);
virtual double __fastcall GetHPFlow(double HP, double dt);
virtual double __fastcall GetCRP(void);
void __fastcall CheckState(double BCP, double &dV1);
void __fastcall CheckReleaser(double dt);
double __fastcall CVs(double bp);
double __fastcall BVs(double BCP);
void __fastcall PLC(double mass);
void __fastcall SetLP(double TM, double LM, double TBP);
void __fastcall SetLBP(double P);
public:
#pragma option push -w-inl
/* TBrake.Create */ inline __fastcall TKE(double i_mbp, double i_bcr, double i_bcd, double i_brc, Byte
i_bcn, Byte i_BD, Byte i_mat, Byte i_ba, Byte i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn,
i_BD, i_mat, i_ba, i_nbpa) { }
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TKE(void) { }
#pragma option pop
};
class DELPHICLASS THandle;
class PASCALIMPLEMENTATION THandle : public System::TObject
{
typedef System::TObject inherited;
public:
bool Time;
bool TimeEP;
double Sounds[5];
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
virtual double __fastcall GetCP(void);
virtual void __fastcall SetReductor(double nAdj);
virtual double __fastcall GetSound(Byte i);
virtual double __fastcall GetPos(Byte i);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall THandle(void) : System::TObject() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~THandle(void) { }
#pragma option pop
};
class DELPHICLASS TFV4a;
class PASCALIMPLEMENTATION TFV4a : public THandle
{
typedef THandle inherited;
private:
double CP;
double TP;
double RP;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFV4a(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFV4a(void) { }
#pragma option pop
};
class DELPHICLASS TFV4aM;
class PASCALIMPLEMENTATION TFV4aM : public THandle
{
typedef THandle inherited;
private:
double CP;
double TP;
double RP;
double XP;
double RedAdj;
bool Fala;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
virtual void __fastcall SetReductor(double nAdj);
virtual double __fastcall GetSound(Byte i);
virtual double __fastcall GetPos(Byte i);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFV4aM(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFV4aM(void) { }
#pragma option pop
};
class DELPHICLASS TM394;
class PASCALIMPLEMENTATION TM394 : public THandle
{
typedef THandle inherited;
private:
double CP;
double RedAdj;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
virtual void __fastcall SetReductor(double nAdj);
virtual double __fastcall GetCP(void);
virtual double __fastcall GetPos(Byte i);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TM394(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TM394(void) { }
#pragma option pop
};
class DELPHICLASS TH14K1;
class PASCALIMPLEMENTATION TH14K1 : public THandle
{
typedef THandle inherited;
private:
double CP;
double RedAdj;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
virtual void __fastcall SetReductor(double nAdj);
virtual double __fastcall GetCP(void);
virtual double __fastcall GetPos(Byte i);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TH14K1(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TH14K1(void) { }
#pragma option pop
};
class DELPHICLASS TSt113;
class PASCALIMPLEMENTATION TSt113 : public TH14K1
{
typedef TH14K1 inherited;
private:
double EPS;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual double __fastcall GetCP(void);
virtual double __fastcall GetPos(Byte i);
virtual void __fastcall Init(double press);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TSt113(void) : TH14K1() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TSt113(void) { }
#pragma option pop
};
class DELPHICLASS Ttest;
class PASCALIMPLEMENTATION Ttest : public THandle
{
typedef THandle inherited;
private:
double CP;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall Ttest(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~Ttest(void) { }
#pragma option pop
};
class DELPHICLASS TFD1;
class PASCALIMPLEMENTATION TFD1 : public THandle
{
typedef THandle inherited;
private:
double MaxBP;
double BP;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
virtual double __fastcall GetCP(void);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFD1(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFD1(void) { }
#pragma option pop
};
class DELPHICLASS TH1405;
class PASCALIMPLEMENTATION TH1405 : public THandle
{
typedef THandle inherited;
private:
double MaxBP;
double BP;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual void __fastcall Init(double press);
virtual double __fastcall GetCP(void);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TH1405(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TH1405(void) { }
#pragma option pop
};
class DELPHICLASS TFVel6;
class PASCALIMPLEMENTATION TFVel6 : public THandle
{
typedef THandle inherited;
private:
double EPS;
public:
virtual double __fastcall GetPF(double i_bcp, double pp, double hp, double dt, double ep);
virtual double __fastcall GetCP(void);
virtual double __fastcall GetPos(Byte i);
virtual double __fastcall GetSound(Byte i);
virtual void __fastcall Init(double press);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TFVel6(void) : THandle() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TFVel6(void) { }
#pragma option pop
};
//-- var, const, procedure ---------------------------------------------------
static const Shortint LocalBrakePosNo = 0xa;
static const Shortint MainBrakeMaxPos = 0xa;
static const Shortint bdelay_G = 0x1;
static const Shortint bdelay_P = 0x2;
static const Shortint bdelay_R = 0x4;
static const Shortint bdelay_M = 0x8;
static const Byte bdelay_GR = 0x80;
static const Shortint b_off = 0x0;
static const Shortint b_hld = 0x1;
static const Shortint b_on = 0x2;
static const Shortint b_rfl = 0x4;
static const Shortint b_rls = 0x8;
static const Shortint b_ep = 0x10;
static const Shortint b_asb = 0x20;
static const Byte b_dmg = 0x80;
static const Shortint df_on = 0x1;
static const Shortint df_off = 0x2;
static const Shortint df_br = 0x4;
static const Shortint df_vv = 0x8;
static const Shortint df_bc = 0x10;
static const Shortint df_cv = 0x20;
static const Shortint df_PP = 0x40;
static const Byte df_RR = 0x80;
static const Shortint s_fv4a_b = 0x0;
static const Shortint s_fv4a_u = 0x1;
static const Shortint s_fv4a_e = 0x2;
static const Shortint s_fv4a_x = 0x3;
static const Shortint s_fv4a_t = 0x4;
static const Shortint bp_P10 = 0x0;
static const Shortint bp_P10Bg = 0x2;
static const Shortint bp_P10Bgu = 0x1;
static const Shortint bp_LLBg = 0x4;
static const Shortint bp_LLBgu = 0x3;
static const Shortint bp_LBg = 0x6;
static const Shortint bp_LBgu = 0x5;
static const Shortint bp_KBg = 0x8;
static const Shortint bp_KBgu = 0x7;
static const Shortint bp_D1 = 0x9;
static const Shortint bp_D2 = 0xa;
static const Shortint bp_FR513 = 0xb;
static const Shortint bp_Cosid = 0xc;
static const Shortint bp_PKPBg = 0xd;
static const Shortint bp_PKPBgu = 0xe;
static const Byte bp_MHS = 0x80;
static const Shortint bp_P10yBg = 0xf;
static const Shortint bp_P10yBgu = 0x10;
static const Shortint sf_Acc = 0x1;
static const Shortint sf_BR = 0x2;
static const Shortint sf_CylB = 0x4;
static const Shortint sf_CylU = 0x8;
static const Shortint sf_rel = 0x10;
static const Shortint sf_ep = 0x20;
static const Shortint bh_MIN = 0x0;
static const Shortint bh_MAX = 0x1;
static const Shortint bh_FS = 0x2;
static const Shortint bh_RP = 0x3;
static const Shortint bh_NP = 0x4;
static const Shortint bh_MB = 0x5;
static const Shortint bh_FB = 0x6;
static const Shortint bh_EB = 0x7;
static const Shortint bh_EPR = 0x8;
static const Shortint bh_EPN = 0x9;
static const Shortint bh_EPB = 0xa;
#define SpgD (7.917000E-01)
#define SpO (5.067000E-01)
extern PACKAGE double BPT[9][2];
extern PACKAGE double BPT_394[7][2];
static const Shortint i_bcpno = 0x6;
extern PACKAGE double __fastcall PF(double P1, double P2, double S, double DP);
extern PACKAGE double __fastcall PF1(double P1, double P2, double S);
extern PACKAGE double __fastcall PFVa(double PH, double PL, double S, double LIM, double DP);
extern PACKAGE double __fastcall PFVd(double PH, double PL, double S, double LIM, double DP);
} /* namespace Hamulce */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace Hamulce;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // hamulce

3014
McZapkie/hamulce.pas Normal file

File diff suppressed because it is too large Load Diff

61
McZapkie/klasy_ham.pas Normal file
View File

@@ -0,0 +1,61 @@
unit klasy_ham; {fizyka hamulcow dla symulatora}
(*
MaSzyna EU07 - SPKS
Brakes. Basic classes.
Copyright (C) 2007-2013 Maciej Cierniak
*)
interface
uses mctools,sysutils;
//CONST;
TYPE
TRurka= class //bezposrednie polaczenie, co wleci to wyleci
private
Vol: real;
Cap: real;
public
function Update(dt: real);
procedure Flow(dV: real);
end;
PRurka= ^TRurka;
TTrojnik= class(TRurka)
private
Wyjscie1: PRurka;
Wyjscie2: PRurka;
Wyjscie3: PRurka;
public
end;
TZbiornik= class(TRurka)
private
Wyjscie_jeden: PRurka;
public
end;
TPowtarzacz= class(TRurka)
private
public
end;
TPrzekladnik= class(TPowtarzacz)
private
public
end;
function PF(P1,P2,S:real):real;
implementation
end.

95
McZapkie/mctools.hpp Normal file
View File

@@ -0,0 +1,95 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) 'mctools.pas' rev: 5.00
#ifndef mctoolsHPP
#define mctoolsHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace Mctools
{
//-- type declarations -------------------------------------------------------
typedef Set<char, 0, 255> TableChar;
//-- var, const, procedure ---------------------------------------------------
#define _EOL (System::Set<char, 0, 255> () << '\xa' << '\xd' )
static const char _SPACE = '\x20';
#define _Spacesigns (System::Set<char, 0, 255> () << '\x9' << '\xa' << '\xd' << '\x29' << '\x2a' << '\x2d' \
<< '\x49' << '\x4a' << '\x4d' << '\x69' << '\x6a' << '\x6d' << '\x89' << '\x8a' << '\x8d' << '\xa9' \
<< '\xaa' << '\xad' << '\xc9' << '\xca' << '\xcd' << '\xe9' << '\xea' << '\xed' )
static const Shortint CutLeft = 0xffffffff;
static const Shortint CutRight = 0x1;
static const Shortint CutBoth = 0x0;
extern PACKAGE int ConversionError;
extern PACKAGE int LineCount;
extern PACKAGE bool DebugModeFlag;
extern PACKAGE bool FreeFlyModeFlag;
extern PACKAGE double Xmin;
extern PACKAGE double Ymin;
extern PACKAGE double Xmax;
extern PACKAGE double Ymax;
extern PACKAGE double Xaspect;
extern PACKAGE double Yaspect;
extern PACKAGE double Hstep;
extern PACKAGE double Vstep;
extern PACKAGE int Vsize;
extern PACKAGE int Hsize;
extern PACKAGE AnsiString __fastcall Ups(AnsiString s);
extern PACKAGE AnsiString __fastcall b2s(Byte b);
extern PACKAGE AnsiString __fastcall i2s(int i);
extern PACKAGE AnsiString __fastcall l2s(int l);
extern PACKAGE AnsiString __fastcall r2s(double r, Byte SWidth);
extern PACKAGE Byte __fastcall s2b(AnsiString s);
extern PACKAGE int __fastcall s2i(AnsiString s);
extern PACKAGE int __fastcall s2l(AnsiString s);
extern PACKAGE double __fastcall s2r(AnsiString s);
extern PACKAGE Byte __fastcall s2bE(AnsiString s);
extern PACKAGE int __fastcall s2iE(AnsiString s);
extern PACKAGE int __fastcall s2lE(AnsiString s);
extern PACKAGE double __fastcall s2rE(AnsiString s);
extern PACKAGE Byte __fastcall Max0(Byte x1, Byte x2);
extern PACKAGE Byte __fastcall Min0(Byte x1, Byte x2);
extern PACKAGE double __fastcall Max0R(double x1, double x2);
extern PACKAGE double __fastcall Min0R(double x1, double x2);
extern PACKAGE int __fastcall Sign(double x);
extern PACKAGE bool __fastcall TestFlag(int Flag, int Value);
extern PACKAGE bool __fastcall SetFlag(Byte &Flag, int Value);
extern PACKAGE bool __fastcall iSetFlag(int &Flag, int Value);
extern PACKAGE bool __fastcall FuzzyLogic(double Test, double Threshold, double Probability);
extern PACKAGE bool __fastcall FuzzyLogicAI(double Test, double Threshold, double Probability);
extern PACKAGE AnsiString __fastcall ReadWord(TextFile &infile);
extern PACKAGE AnsiString __fastcall Cut_Space(AnsiString s, int Just);
extern PACKAGE AnsiString __fastcall ExtractKeyWord(AnsiString InS, AnsiString KeyWord);
extern PACKAGE AnsiString __fastcall DUE(AnsiString S);
extern PACKAGE AnsiString __fastcall DWE(AnsiString S);
extern PACKAGE AnsiString __fastcall Ld2Sp(AnsiString S);
extern PACKAGE AnsiString __fastcall Tab2Sp(AnsiString S);
extern PACKAGE void __fastcall ComputeArc(double X0, double Y0, double Xn, double Yn, double R, double
L, double dL, double &phi, double &Xout, double &Yout);
extern PACKAGE void __fastcall ComputeALine(double X0, double Y0, double Xn, double Yn, double L, double
R, double &Xout, double &Yout);
extern PACKAGE double __fastcall Xhor(double h);
extern PACKAGE double __fastcall Yver(double v);
extern PACKAGE int __fastcall Horiz(double X);
extern PACKAGE int __fastcall Vert(double Y);
extern PACKAGE void __fastcall ClearPendingExceptions(void);
} /* namespace Mctools */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace Mctools;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // mctools

497
McZapkie/mctools.pas Normal file
View File

@@ -0,0 +1,497 @@
unit mctools;
{rozne takie duperele do operacji na stringach w paszczalu, pewnie w delfi sa lepsze}
{konwersja zmiennych na stringi, funkcje matematyczne, logiczne, lancuchowe, I/O etc}
interface
const
{Ra: te sta³e nie s¹ u¿ywane...
_FileName = ['a'..'z','A'..'Z',':','\','.','*','?','0'..'9','_','-'];
_RealNum = ['0'..'9','-','+','.','E','e'];
_Integer = ['0'..'9','-']; //Ra: to siê gryzie z STLport w Builder 6
_Plus_Int = ['0'..'9'];
_All = [' '..'þ'];
_Delimiter= [',',';']+_EOL;
_Delimiter_Space=_Delimiter+[' '];
}
_EOL = [#13,#10];
_SPACE = ' ';
_Spacesigns=[' ']+[#9]+_EOL;
CutLeft=-1; CutRight=1; CutBoth=0; {Cut_Space}
var
ConversionError: integer=0;
LineCount: integer=0;
DebugModeFlag: boolean=False;
FreeFlyModeFlag: boolean=False;
type
TableChar = Set Of Char; {MCTUTIL}
{konwersje}
function b2s(b:byte):string;
function i2s(i:integer):string;
function l2s(l:longint):string;
function r2s(r:real; SWidth:byte):string;
function s2b(s:string):byte;
function s2i(s:string):integer;
function s2l(s:string):longint;
function s2r(s:string):real;
function s2bE(s:string):byte;
function s2iE(s:string):integer;
function s2lE(s:string):longint;
function s2rE(s:string):real;
{funkcje matematyczne}
function Max0(x1,x2:byte) : byte;
function Min0(x1,x2:byte) : byte;
function Max0R(x1,x2:real) : real;
function Min0R(x1,x2:real) : real;
function Sign(x:real) : integer;
{funkcje logiczne}
function TestFlag(Flag:integer; Value:integer):boolean;
function SetFlag(var Flag:byte; Value:integer):boolean;
function iSetFlag(var Flag:integer; Value:integer):boolean;
function FuzzyLogic(Test,Threshold,Probability:real):boolean;
{jesli Test>Threshold to losowanie}
function FuzzyLogicAI(Test,Threshold,Probability:real):boolean;
{to samo ale zawsze niezaleznie od DebugFlag}
{operacje na stringach}
Function ReadWord(var infile:text):string; {czyta slowo z wiersza pliku tekstowego}
Function Ups (s:string ): string ;
Function Cut_Space(s:string; Just:integer) : string;
Function ExtractKeyWord(InS:String; KeyWord:string) : String; {wyciaga slowo kluczowe i lancuch do pierwszej spacji}
Function DUE(S:String) : String; {Delete Until Equal sign}
Function DWE(S:String) : String; {Delete While Equal sign}
Function Ld2Sp(S:String): String; {Low dash to Space sign}
Function Tab2Sp(S:String): String; {Tab to Space sign}
{procedury, zmienne i funkcje graficzne}
procedure ComputeArc(X0,Y0,Xn,Yn,R,L:real;dL:real; var phi,Xout,Yout:real);
{wylicza polozenie Xout Yout i orientacje phi punktu na elemencie dL luku}
procedure ComputeALine(X0,Y0,Xn,Yn,L,R:real; var Xout,Yout:real);
var
Xmin,Ymin,Xmax,Ymax:real;
Xaspect,Yaspect:real;
Hstep,Vstep: real;
Vsize,Hsize:integer;
function Xhor( h:real) :real;
{ Converts horizontal screen coordinate into real X-coordinate. }
function Yver( v:real) :real;
{ Converts vertical screen coordinate into real Y-coordinate. }
function Horiz(X:real):longint;
function Vert(Y:real):longint;
procedure ClearPendingExceptions;
{------------------------------------------------}
Implementation
{================================================}
function Ups (s:string ): string ;
var
jatka : integer; swy:string;
begin
swy:='';
for jatka:=1 to length(s) do swy:=swy+UpCase(s[jatka]);
Ups:=swy;
end; {=Ups=}
function b2s(b:byte):string;
var
s:string;
begin
Str(b:2,s);
b2s:=s;
end; {=b2s=}
function i2s(i:integer):string;
var
s:string;
begin
Str(i:3,s);
i2s:=s;
end; {=i2s=}
function l2s(l:longint):string;
var
s:string;
begin
Str(l:4,s);
l2s:=s;
end; {=l2s=}
function r2s(r:real; SWidth:byte):string;
var
s:string;
absr:real; {rr:integer;}
begin
absr:=Abs(r);
if SWidth<8 then SWidth:=8;
if absr > 0.0001 then
begin {rr:=(Round(ln(1/absr)/ln(10)-1+Swidth/2));}
if absr < 100 then
Str(r:Swidth:(Round(ln(1/absr)/ln(10)-1+Swidth/2)),s)
else Str(r:Swidth:1,s)
end
else Str(r:Swidth,s);
{ if r>0 then s:=insert('+'s,3);}
r2s:=s;
end; {=r2s=}
function s2b(s:string):byte;
var e:integer;
b:byte;
begin
Val(s,b,e);
s2b:=b;
end;
function s2i(s:string):integer;
var e:integer;
i:integer;
begin
Val(s,i,e);
s2i:=i;
end;
function s2l(s:string):longint;
var e:integer;
l:longint;
begin
Val(s,l,e);
s2l:=l;
end;
function s2r(s:string):real;
var e:integer;
r:real;
begin
Val(s,r,e);
s2r:=r;
end;
function s2bE(s:string):byte;
var e:integer;
b:byte;
begin
s2bE:=0;
Val(s,b,e);
if e>0 then
ConversionError:=e
else s2bE:=b;
end;
function s2iE(s:string):integer;
var e:integer;
i:integer;
begin
s2iE:=0;
Val(s,i,e);
if e>0 then
ConversionError:=e
else s2iE:=i;
end;
function s2lE(s:string):longint;
var e:integer;
l:longint;
begin
s2lE:=0;
Val(s,l,e);
if e>0 then
ConversionError:=e
else s2lE:=l;
end;
function s2rE(s:string):real;
var e:integer;
r:real;
begin
s2rE:=0;
Val(s,r,e);
if e>0 then
ConversionError:=e
else s2rE:=r;
end;
function Max0(x1,x2:byte) : byte;
begin
if x1>x2 then
Max0:=x1
else
Max0:=x2;
end;
function Min0(x1,x2:byte) : byte;
begin
if x1<x2 then
Min0:=x1
else
Min0:=x2;
end;
function Max0R(x1,x2:real) : real;
begin
if x1>x2 then
Max0R:=x1
else
Max0R:=x2;
end;
function Min0R(x1,x2:real) : real;
begin
if x1<x2 then
Min0R:=x1
else
Min0R:=x2;
end;
function Sign(x:real) : integer;
begin
Sign:=0;
if x>0 then Sign:=1;
if x<0 then Sign:=-1;
end;
function TestFlag(Flag:integer; Value:integer):boolean;
begin
if (Flag and Value)=Value then
TestFlag:=True
else TestFlag:=False;
end;
function SetFlag(var Flag:byte; Value:integer):boolean;
begin
SetFlag:=False;
if Value>0 then
if (Flag and Value)=0 then
begin
Flag:=Flag+Value;
SetFlag:=True
end;
if Value<0 then
if (Flag and Abs(Value))=Abs(Value) then
begin
Flag:=Flag+Value;
SetFlag:=True
end;
end;
function iSetFlag(var Flag:integer; Value:integer):boolean;
begin
iSetFlag:=False;
if Value>0 then
if (Flag and Value)=0 then
begin
Flag:=Flag+Value;
iSetFlag:=True; //true, gdy by³o wczeœniej 0 i zosta³o ustawione
end;
if Value<0 then
if (Flag and Abs(Value))=Abs(Value) then
begin
Flag:=Flag+Value; //Value jest ujemne, czyli zerowanie flagi
iSetFlag:=True; //true, gdy by³o wczeœniej 1 i zosta³o wyzerowane
end;
end;
function FuzzyLogic(Test,Threshold,Probability:real):boolean;
begin
if (Test>Threshold) and (not DebugModeFlag) then
FuzzyLogic:=(Random<Probability*Threshold/Test) {im wiekszy Test tym wieksza szansa}
else FuzzyLogic:=False;
end;
function FuzzyLogicAI(Test,Threshold,Probability:real):boolean;
begin
if (Test>Threshold) then
FuzzyLogicAI:=(Random<Probability*Threshold/Test) {im wiekszy Test tym wieksza szansa}
else FuzzyLogicAI:=False;
end;
Function ReadWord(var infile:text):string;
var s:string; c:char; nextword:boolean;
begin
s:='';
nextword:=False;
while (not eof(infile)) and (not nextword) do
begin
read(infile,c);
if c in _SpaceSigns then
if s<>'' then
nextword:=True;
if not (c in _Spacesigns) then
s:=s+c;
end;
ReadWord:=s;
end;
Function Cut_Space(s:string; Just:integer) : string;
var ii:byte;
begin
case Just of
CutLeft : begin
ii:=0;
while (ii<length(s)) and (s[ii+1]=_SPACE) do
inc(ii);
S:=Copy(s,ii+1,length(s)-ii);
end;
CutRight: begin
ii:=length(s);
while(ii>0) and (s[ii]=_SPACE) do
dec(ii);
S:=Copy(s,1,ii);
end;
CutBoth : begin
S:=Cut_Space(S,CutLeft);
S:=Cut_Space(S,CutRight);
end;
end;
Cut_Space:=S;
end;
{Cut_Space}
Function ExtractKeyWord(InS:String; KeyWord:string) : String;
var s:string; kwp:byte;
begin
Ins:=Ins+' ';
kwp:=Pos(KeyWord,InS);
if kwp>0 then
begin
s:=Copy(InS,kwp,Length(Ins));
s:=Copy(s,1,Pos(' ',s)-1);
end
else s:='';
ExtractKeyWord:=s;
end;
Function DUE(S:String) : String; {Delete Until Equal sign}
begin
DUE:=Copy(S,Pos('=',S)+1,Length(S));
end;
Function DWE(S:String) : String; {Delete While Equal sign}
var ep:byte;
begin
ep:=Pos('=',S);
if ep>0 then
DWE:=Copy(S,1,ep-1)
else DWE:=S;
end;
Function Ld2Sp(S:String): String; {Low dash to Space sign}
var b:byte; s2:string;
begin
s2:='';
for b:=1 to length(S) do
if S[b]='_' then
s2:=s2+' '
else
s2:=s2+S[b];
Ld2Sp:=s2;
end;
Function Tab2Sp(S:String): String; {Tab to Space sign}
var b:byte; s2:string;
begin
s2:='';
for b:=1 to length(S) do
if S[b]=#9 then
s2:=s2+' '
else
s2:=s2+S[b];
Tab2Sp:=s2;
end;
procedure ComputeArc(X0,Y0,Xn,Yn,R,L:real;dL:real; var phi,Xout,Yout:real);
{wylicza polozenie Xout Yout i orientacje phi punktu na elemencie dL luku}
var dX,dY,Xc,Yc,gamma,alfa,AbsR:real;
begin
if (R<>0) and (L<>0) then
begin
AbsR:=Abs(R);
dX:=Xn-X0;
dY:=Yn-Y0;
if dX<>0 then gamma:=arctan(dY/dX)
else if dY>0 then gamma:=Pi/2
else gamma:=3*Pi/2;
alfa:=L/R;
phi:=gamma-(alfa+Pi*Round(R/AbsR))/2;
Xc:=X0-AbsR*cos(phi);
Yc:=Y0-AbsR*sin(phi);
phi:=phi+alfa*dL/L;
Xout:=AbsR*cos(phi)+Xc;
Yout:=AbsR*sin(phi)+Yc;
end;
end;
procedure ComputeALine(X0,Y0,Xn,Yn,L,R:real; var Xout,Yout:real);
var dX,dY,gamma,alfa:real;
{ pX,pY : real;}
begin
alfa:=0; //ABu: bo nie bylo zainicjowane
dX:=Xn-X0;
dY:=Yn-Y0;
if dX<>0 then gamma:=arctan(dY/dX)
else if dY>0 then gamma:=Pi/2
else gamma:=3*Pi/2;
if R<>0 then alfa:=L/R;
Xout:=X0+L*cos(alfa/2-gamma);
Yout:=Y0+L*sin(alfa/2-gamma);
end;
{graficzne:}
function Xhor( h:real) :real;
begin
Xhor:= h*Hstep + Xmin;
end;
function Yver( v:real) :real;
begin
Yver:= (Vsize-v)*Vstep + Ymin;
end;
function Horiz(X:real):longint;
begin
x:= (x-Xmin) / Hstep;
if x > -MaxInt then
if x < MaxInt then Horiz:=Round(x)
else Horiz:= MaxInt
else Horiz:= -MaxInt;
end;
function Vert(Y:real):longint;
begin
y:= (y-Ymin) / Vstep;
if y > -MaxInt then
if y < MaxInt then Vert:=Vsize-Round(y)
else Vert:= MaxInt
else Vert:= -MaxInt
end;
procedure ClearPendingExceptions;
//resetuje b³êdy FPU, wymagane dla Trunc()
asm
FNCLEX
end;
end.

127
McZapkie/mtable.hpp Normal file
View File

@@ -0,0 +1,127 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) 'mtable.pas' rev: 5.00
#ifndef mtableHPP
#define mtableHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <SysUtils.hpp> // Pascal unit
#include <mctools.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace Mtable
{
//-- type declarations -------------------------------------------------------
struct TMTableLine
{
double km;
double vmax;
AnsiString StationName;
AnsiString StationWare;
Byte TrackNo;
int Ah;
int Am;
int Dh;
int Dm;
double tm;
int WaitTime;
} ;
typedef TMTableLine TMTable[101];
class DELPHICLASS TTrainParameters;
typedef TTrainParameters* *PTrainParameters;
class PASCALIMPLEMENTATION TTrainParameters : public System::TObject
{
typedef System::TObject inherited;
public:
AnsiString TrainName;
double TTVmax;
AnsiString Relation1;
AnsiString Relation2;
double BrakeRatio;
AnsiString LocSeries;
double LocLoad;
TMTableLine TimeTable[101];
int StationCount;
int StationIndex;
AnsiString NextStationName;
double LastStationLatency;
int Direction;
double __fastcall CheckTrainLatency(void);
AnsiString __fastcall ShowRelation();
double __fastcall WatchMTable(double DistCounter);
AnsiString __fastcall NextStop();
bool __fastcall IsStop(void);
bool __fastcall IsTimeToGo(double hh, double mm);
bool __fastcall UpdateMTable(double hh, double mm, AnsiString NewName);
__fastcall TTrainParameters(AnsiString NewTrainName);
void __fastcall NewName(AnsiString NewTrainName);
bool __fastcall LoadTTfile(AnsiString scnpath, int iPlus, double vMax);
bool __fastcall DirectionChange(void);
void __fastcall StationIndexInc(void);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TTrainParameters(void) : System::TObject() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TTrainParameters(void) { }
#pragma option pop
};
class DELPHICLASS TMTableTime;
class PASCALIMPLEMENTATION TMTableTime : public System::TObject
{
typedef System::TObject inherited;
public:
double GameTime;
int dd;
int hh;
int mm;
int srh;
int srm;
int ssh;
int ssm;
double mr;
void __fastcall UpdateMTableTime(double deltaT);
__fastcall TMTableTime(int InitH, int InitM, int InitSRH, int InitSRM, int InitSSH, int InitSSM);
public:
#pragma option push -w-inl
/* TObject.Create */ inline __fastcall TMTableTime(void) : System::TObject() { }
#pragma option pop
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TMTableTime(void) { }
#pragma option pop
};
//-- var, const, procedure ---------------------------------------------------
static const Shortint MaxTTableSize = 0x64;
static const char hrsd = '\x2e';
extern PACKAGE TMTableTime* GlobalTime;
} /* namespace Mtable */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace Mtable;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // mtable

521
McZapkie/mtable.pas Normal file
View File

@@ -0,0 +1,521 @@
unit mtable;
interface uses mctools,sysutils;
const MaxTTableSize=100; //mo¿na by to robiæ dynamicznie
hrsd= '.';
Type
//Ra: pozycja zerowa rozk³adu chyba nie ma sensu
//Ra: numeracja przystanków jest 1..StationCount
TMTableLine=record
km:real; //kilometraz linii
vmax:real; //predkosc rozkladowa przed przystankiem
//StationName:string[32]; //nazwa stacji ('_' zamiast spacji)
//StationWare:string[32]; //typ i wyposazenie stacji, oddz. przecinkami}
StationName:string; //nazwa stacji ('_' zamiast spacji)
StationWare:string; //typ i wyposazenie stacji, oddz. przecinkami}
TrackNo:byte; //ilosc torow szlakowych
Ah,Am:integer; //godz. i min. przyjazdu, -1 gdy bez postoju
Dh,Dm:integer; //godz. i min. odjazdu
tm:real; //czas jazdy do tej stacji w min. (z kolumny)
WaitTime:integer; //czas postoju (liczony plus 6 sekund)
end;
TMTable = array[0..MaxTTableSize] of TMTableLine;
PTrainParameters= ^TTrainParameters;
TTrainParameters = class(TObject)
TrainName:string;
TTVmax:real;
Relation1,Relation2: string; //nazwy stacji danego odcinka
BrakeRatio: real;
LocSeries: string; //seria (typ) pojazdu
LocLoad: real;
TimeTable: TMTable;
StationCount: integer; //iloœæ przystanków (0-techniczny)
StationIndex: integer; //numer najbli¿szego (aktualnego) przystanku
NextStationName: string;
LastStationLatency: real;
Direction: integer; {kierunek jazdy w/g kilometrazu}
function CheckTrainLatency: real;
{todo: str hh:mm to int i z powrotem}
function ShowRelation: string;
function WatchMTable(DistCounter:real): real;
function NextStop:string;
function IsStop:boolean;
function IsTimeToGo(hh,mm:real):boolean;
function UpdateMTable(hh,mm:real; NewName: string): boolean;
constructor Init(NewTrainName:string);
procedure NewName(NewTrainName:string);
function LoadTTfile(scnpath:string;iPlus:Integer;vMax:real):boolean;
function DirectionChange():boolean;
procedure StationIndexInc();
end;
TMTableTime = class(TObject)
GameTime: real;
dd,hh,mm: integer;
srh,srm : integer; {wschod slonca}
ssh,ssm : integer; {zachod slonca}
mr:real;
procedure UpdateMTableTime(deltaT:real);
constructor Init(InitH,InitM,InitSRH,InitSRM,InitSSH,InitSSM:integer);
end;
var GlobalTime: TMTableTime;
implementation
function CompareTime(t1h,t1m,t2h,t2m:real):real; {roznica czasu w minutach}
//zwraca ró¿nicê czasu
//jeœli pierwsza jest aktualna, a druga rozk³adowa, to ujemna oznacza opó¿nienie
//na d³u¿sz¹ metê trzeba uwzglêdniæ datê, jakby opó¿nienia mia³y przekraczaæ 12h (towarowych)
var
t:real;
begin
if (t2h<0) then
CompareTime:=0
else
begin
t:=(t2h-t1h)*60+t2m-t1m; //jeœli t2=00:05, a t1=23:50, to ró¿nica wyjdzie ujemna
if (t<-720) then //jeœli ró¿nica przekracza 12h na minus
t:=t+1440 //to dodanie doby minut
else
if (t>720) then //jeœli przekracza 12h na plus
t:=t-1440; //to odjêcie doby minut
CompareTime:=t;
end;
end;
function TTrainParameters.CheckTrainLatency: real;
begin
if (LastStationLatency>1.0) or (LastStationLatency<-1.0) then
CheckTrainLatency:=LastStationLatency {spoznienie + lub do przodu - z tolerancja 1 min}
else
CheckTrainLatency:=0
end;
function TTrainParameters.WatchMTable(DistCounter:real): real;
{zwraca odlegloϾ do najblizszej stacji z zatrzymaniem}
var dist:real;
begin
if Direction=1 then
dist:=TimeTable[StationIndex].km-TimeTable[0].km-DistCounter
else
dist:=TimeTable[0].km-TimeTable[StationIndex].km-DistCounter;
WatchMTable:=dist;
end;
function TTrainParameters.NextStop:string;
//pobranie nazwy nastêpnego miejsca zatrzymania
begin
if StationIndex<=StationCount
then
NextStop:='PassengerStopPoint:'+NextStationName //nazwa nastêpnego przystanku
else
NextStop:='[End of route]'; //¿e niby koniec
end;
function TTrainParameters.IsStop:boolean;
//zapytanie, czy zatrzymywaæ na nastêpnym punkcie rozk³adu
begin
if (StationIndex<StationCount) then
IsStop:=TimeTable[StationIndex].Ah>=0 //-1 to brak postoju
else
IsStop:=true; //na ostatnim siê zatrzymaæ zawsze
end;
function TTrainParameters.UpdateMTable(hh,mm:real;NewName:string):boolean;
{odfajkowanie dojechania do stacji (NewName) i przeliczenie opóŸnienia}
var OK:boolean;
begin
OK:=false;
if StationIndex<=StationCount then //Ra: "<=", bo ostatni przystanek jest traktowany wyj¹tkowo
begin
if NewName=NextStationName then //jeœli dojechane do nastêpnego
begin //Ra: wywo³anie mo¿e byæ powtarzane, jak stoi na W4
if TimeTable[StationIndex+1].km-TimeTable[StationIndex].km<0 then //to jest bez sensu
Direction:=-1
else
Direction:=1; //prowizorka bo moze byc zmiana kilometrazu
//ustalenie, czy opóŸniony (porównanie z czasem odjazdu)
LastStationLatency:=CompareTime(hh,mm,TimeTable[StationIndex].Dh,TimeTable[StationIndex].Dm);
//inc(StationIndex); //przejœcie do nastêpnej pozycji StationIndex<=StationCount
if StationIndex<StationCount then //Ra: "<", bo dodaje 1 przy przejœciu do nastêpnej stacji
begin //jeœli nie ostatnia stacja
NextStationName:=TimeTable[StationIndex+1].StationName; //zapamiêtanie nazwy
TTVmax:=TimeTable[StationIndex+1].vmax; //Ra: nowa prêdkoœæ rozk³adowa na kolejnym odcinku
end
else //gdy ostatnia stacja
NextStationName:=''; //nie ma nastêpnej stacji
OK:=true;
end;
end;
UpdateMTable:=OK; {czy jest nastepna stacja}
end;
procedure TTrainParameters.StationIndexInc();
begin
Inc(StationIndex); //przejœcie do nastêpnej pozycji StationIndex<=StationCount
end;
function TTrainParameters.IsTimeToGo(hh,mm:real):boolean;
//sprawdzenie, czy mo¿na ju¿ odjechaæ z aktualnego zatrzymania
//StationIndex to numer nastêpnego po dodarciu do aktualnego
begin
if (StationIndex<1) then
IsTimeToGo:=true //przed pierwsz¹ jechaæ
else if (StationIndex<StationCount) then
begin //oprócz ostatniego przystanku
if (TimeTable[StationIndex].Ah<0) then //odjazd z poprzedniego
IsTimeToGo:=true //czas przyjazdu nie by³ podany - przelot
else
IsTimeToGo:=CompareTime(hh,mm,TimeTable[StationIndex].Dh,TimeTable[StationIndex].Dm)<=0;
end
else //gdy rozk³ad siê skoñczy³
IsTimeToGo:=false; //dalej nie jechaæ
end;
function TTrainParameters.ShowRelation:string;
{zwraca informacjê o relacji}
begin
//if (Relation1=TimeTable[1].StationName) and (Relation2=TimeTable[StationCount].StationName)
if (Relation1<>'') and (Relation2<>'')
then ShowRelation:=Relation1+' - '+Relation2
else ShowRelation:='';
end;
constructor TTrainParameters.Init(NewTrainName:string);
{wstêpne ustawienie parametrów rozk³adu jazdy}
begin
NewName(NewTrainName);
end;
procedure TTrainParameters.NewName(NewTrainName:string);
{wstêpne ustawienie parametrów rozk³adu jazdy}
var i:integer;
begin
TrainName:=NewTrainName;
StationCount:=0;
StationIndex:=0;
NextStationName:='nowhere';
LastStationLatency:=0;
Direction:=1;
Relation1:=''; Relation2:='';
for i:=0 to MaxTTableSize do
with timeTable[i] do
begin
km:=0; vmax:=-1; StationName:='nowhere'; StationWare:='';
TrackNo:=1; Ah:=-1; Am:=-1; Dh:=-1; Dm:=-1; tm:=0; WaitTime:=0;
end;
TTVmax:=100; {wykasowac}
end;
function TTrainParameters.LoadTTfile(scnpath:string;iPlus:Integer;vMax:real):boolean;
//wczytanie pliku-tabeli z rozk³adem przesuniêtym o (fPlus); (vMax) nie ma znaczenia
var
lines,s:string;
fin:text;
EndTable:boolean;
vActual:real;
i,time:Integer; //do zwiêkszania czasu
procedure UpdateVelocity(StationCount:integer;vActual:real);
//zapisywanie prêdkoœci maksymalnej do wczeœniejszych odcinków
//wywo³ywane z numerem ostatniego przetworzonego przystanku
var i:integer;
begin
i:=StationCount;
//TTVmax:=vActual; {PROWIZORKA!!!}
while (i>=0) and (TimeTable[i].vmax=-1) do
begin
TimeTable[i].vmax:=vActual; //prêdkoœæ dojazdu do przystanku i
dec(i); //ewentualnie do poprzedniego te¿
end;
end;
begin
ClearPendingExceptions;
ConversionError:=0;
EndTable:=False;
if (TrainName='') then
begin //jeœli pusty rozk³ad
//UpdateVelocity(StationCount,vMax); //ograniczenie do prêdkoœci startowej
end
else
begin
ConversionError:=666;
vActual:=-1;
s:=scnpath+TrainName+'.txt';
//Ra 2014-09: ustaliæ zasady wyznaczenia pierwotnego pliku przy przesuniêtych rozk³adach (kolejny poci¹g dostaje numer +2)
assignfile(fin,s);
s:='';
{$I-}
reset(fin);
{$I+}
if IOresult<>0 then
begin
vMax:=s2r(TrainName); //nie ma pliku ale jest liczba
if (vMax>10)and(vMax<200) then
begin
TTVmax:=vMax; //Ra 2014-07: zamiast rozk³adu mo¿na podaæ Vmax
UpdateVelocity(StationCount,vMax); //ograniczenie do prêdkoœci startowej
ConversionError:=0;
end
else
ConversionError:=-8; {Ra: ten b³¹d jest niepotrzebny}
end
else
begin {analiza rozk³adu jazdy}
ConversionError:=0;
while not (eof(fin) or (ConversionError<>0) or EndTable) do
begin
readln(fin,lines); {wczytanie linii}
if Pos('___________________',lines)>0 then {linia pozioma górna}
if ReadWord(fin)='[' then {lewy pion}
if ReadWord(fin)='Rodzaj' then {"Rodzaj i numer pociagu"}
repeat
until (ReadWord(fin)='|') or (eof(fin)); {œrodkowy pion}
s:=ReadWord(fin); {nazwa poci¹gu}
//if LowerCase(s)<>ExtractFileName(TrainName) then {musi byæ taka sama, jak nazwa pliku}
//ConversionError:=-7 {b³¹d niezgodnoœci}
TrainName:=s; //nadanie nazwy z pliku TXT (bez œcie¿ki do pliku)
//else
begin {czytaj naglowek}
repeat
until (Pos('_______|',ReadWord(fin))>0) or eof(fin);
repeat
until (ReadWord(fin)='[') or (eof(fin)); {pierwsza linia z relacj¹}
repeat
s:=ReadWord(fin);
until (s<>'|') or eof(fin);
if s<>'|' then Relation1:=s
else ConversionError:=-5;
repeat
until (Readword(fin)='Relacja') or (eof(fin)); {druga linia z relacj¹}
repeat
until (ReadWord(fin)='|') or (eof(fin));
Relation2:=ReadWord(fin);
repeat
until Readword(fin)='Wymagany';
repeat
until (ReadWord(fin)='|') or (eoln(fin));
s:=ReadWord(fin);
s:=Copy(s,1,Pos('%',s)-1);
BrakeRatio:=s2rE(s);
repeat
until Readword(fin)='Seria';
repeat
until (ReadWord(fin)='|') or (eof(fin));
LocSeries:=ReadWord(fin);
LocLoad:=s2rE(ReadWord(fin));
repeat
until (Pos('[______________',ReadWord(fin))>0) or (eof(fin));
while not eof(fin) and not EndTable do
begin
inc(StationCount);
repeat
s:=ReadWord(fin);
until (s='[') or (eof(fin));
with TimeTable[StationCount] do
begin
if s='[' then
s:=ReadWord(fin)
else ConversionError:=-4;
if Pos('|',s)=0 then
begin
km:=s2rE(s);
s:=ReadWord(fin);
end;
if Pos('|_____|',s)>0 then {zmiana predkosci szlakowej}
UpdateVelocity(StationCount,vActual)
else
begin
s:=ReadWord(fin);
if Pos('|',s)=0 then
vActual:=s2rE(s);
end;
while Pos('|',s)=0 do
s:=Readword(fin);
StationName:=ReadWord(fin);
repeat
s:=ReadWord(fin);
until (s='1') or (s='2') or eof(fin);
TrackNo:=s2bE(s);
s:=ReadWord(fin);
if s<>'|' then
begin
if Pos(hrsd,s)>0 then
begin
ah:=s2iE(Copy(s,1,Pos(hrsd,s)-1)); //godzina przyjazdu
am:=s2iE(Copy(s,Pos(hrsd,s)+1,Length(s))); //minuta przyjazdu
end
else
begin
ah:=TimeTable[StationCount-1].ah; //godzina z poprzedniej pozycji
am:=s2iE(s); //bo tylko minuty podane
end;
end;
repeat
s:=ReadWord(fin);
until (s<>'|') or (eof(fin));
if s<>']' then
tm:=s2rE(s);
repeat
s:=ReadWord(fin);
until (s='[') or eof(fin);
s:=ReadWord(fin);
if Pos('|',s)=0 then
begin
{tu s moze byc miejscem zmiany predkosci szlakowej}
s:=ReadWord(fin);
end;
if Pos('|_____|',s)>0 then {zmiana predkosci szlakowej}
UpdateVelocity(StationCount,vActual)
else
begin
s:=ReadWord(fin);
if Pos('|',s)=0 then
vActual:=s2rE(s);
end;
while Pos('|',s)=0 do
s:=Readword(fin);
StationWare:=ReadWord(fin);
repeat
s:=ReadWord(fin);
until (s='1') or (s='2') or eof(fin);
TrackNo:=s2bE(s);
s:=ReadWord(fin);
if s<>'|' then
begin
if Pos(hrsd,s)>0 then
begin
dh:=s2iE(Copy(s,1,Pos(hrsd,s)-1)); //godzina odjazdu
dm:=s2iE(Copy(s,Pos(hrsd,s)+1,Length(s))); //minuta odjazdu
end
else
begin
dh:=TimeTable[StationCount-1].dh; //godzina z poprzedniej pozycji
dm:=s2iE(s); //bo tylko minuty podane
end;
end
else
begin
dh:=ah; //odjazd o tej samej, co przyjazd (dla ostatniego te¿)
dm:=am; //bo s¹ u¿ywane do wyliczenia opóŸnienia po dojechaniu
end;
if (ah>=0) then
WaitTime:=Trunc(CompareTime(ah,am,dh,dm)+0.1);
repeat
s:=ReadWord(fin);
until (s<>'|') or (eof(fin));
if s<>']' then
tm:=s2rE(s);
repeat
s:=ReadWord(fin);
until (Pos('[',s)>0) or eof(fin);
if Pos('_|_',s)=0 then
s:=Readword(fin);
if Pos('|',s)=0 then
begin
{tu s moze byc miejscem zmiany predkosci szlakowej}
s:=ReadWord(fin);
end;
if Pos('|_____|',s)>0 then {zmiana predkosci szlakowej}
UpdateVelocity(StationCount,vActual)
else
begin
s:=ReadWord(fin);
if Pos('|',s)=0 then
vActual:=s2rE(s);
end;
while Pos('|',s)=0 do
s:=Readword(fin);
while (Pos(']',s)=0) do
s:=ReadWord(fin);
if Pos('_|_',s)>0 then EndTable:=True;
end; {timetableline}
end;
end;
end; {while eof}
close(fin);
end;
end;
if ConversionError=0 then
begin
if (TimeTable[1].StationName=Relation1) then //jeœli nazwa pierwszego zgodna z relacj¹
if (TimeTable[1].Ah<0) then //a nie podany czas przyjazdu
begin //to mamy zatrzymanie na pierwszym, a nie przelot
TimeTable[1].Ah:=TimeTable[1].Dh;
TimeTable[1].Am:=TimeTable[1].Dm;
end
//NextStationName:=TimeTable[1].StationName;
{ TTVmax:=TimeTable[1].vmax; }
end;
if (iPlus<>0) then //je¿eli jest przesuniêcie rozk³adu
for i:=1 to StationCount do //bez with, bo ciê¿ko siê przenosi na C++
begin
if (TimeTable[i].Ah>=0) then
begin
time:=iPlus+TimeTable[i].Ah*60+TimeTable[i].Am; //nowe minuty
TimeTable[i].Am:=time mod 60;
TimeTable[i].Ah:=(time div 60) mod 60;
end;
if (TimeTable[i].Dh>=0) then
begin
time:=iPlus+TimeTable[i].Dh*60+TimeTable[i].Dm; //nowe minuty
TimeTable[i].Dm:=time mod 60;
TimeTable[i].Dh:=(time div 60) mod 60;
end;
end;
LoadTTfile:=(ConversionError=0);
end;
procedure TMTableTime.UpdateMTableTime(deltaT:real);
//dodanie czasu (deltaT) w sekundach, z przeliczeniem godziny
begin
mr:=mr+deltaT; //dodawanie sekund
while mr>60.0 do //przeliczenie sekund do w³aœciwego przedzia³u
begin
mr:=mr-60.0;
inc(mm);
end;
while mm>59 do //przeliczenie minut do w³aœciwego przedzia³u
begin
mm:=mm-60;
inc(hh);
end;
while hh>23 do //przeliczenie godzin do w³aœciwego przedzia³u
begin
hh:=hh-24;
inc(dd); //zwiêkszenie numeru dnia
end;
GameTime:=GameTime+deltaT;
end;
constructor TMTableTime.Init(InitH,InitM,InitSRH,InitSRM,InitSSH,InitSSM:integer);
begin
GameTime:=0.0;
dd:=0;
hh:=InitH;
mm:=InitM;
srh:=InitSRH;
srm:=InitSRM;
ssh:=InitSSH;
ssm:=InitSSM;
end;
function TTrainParameters.DirectionChange():boolean;
//sprawdzenie, czy po zatrzymaniu wykonaæ kolejne komendy
begin
DirectionChange:=false; //przed pierwsz¹ bez zmiany
if (StationIndex>0) and (StationIndex<StationCount) then //dla ostatniej stacji nie
if (Pos('@',TimeTable[StationIndex].StationWare)>0) then
DirectionChange:=true;
end;
END.

338
McZapkie/unit2.pas Normal file
View File

@@ -0,0 +1,338 @@
unit Unit1;
interface
uses
ai_driver,mtable,mover,mctools,Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
Label2: TLabel;
Label3: TLabel;
Timer1: TTimer;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Label11: TLabel;
Button7: TButton;
Button8: TButton;
Label12: TLabel;
Label13: TLabel;
Label14: TLabel;
Label15: TLabel;
Button9: TButton;
Button10: TButton;
Label16: TLabel;
Label17: TLabel;
Label18: TLabel;
Label19: TLabel;
Button11: TButton;
Label20: TLabel;
Label21: TLabel;
Label22: TLabel;
Label23: TLabel;
Label24: TLabel;
Label25: TLabel;
lczas: TLabel;
Label26: TLabel;
Label27: TLabel;
Label28: TLabel;
Label29: TLabel;
Label30: TLabel;
Label31: TLabel;
Label32: TLabel;
Label33: TLabel;
Label34: TLabel;
Button12: TButton;
BStart: TButton;
Label35: TLabel;
Label36: TLabel;
Label37: TLabel;
Label38: TLabel;
Button13: TButton;
Label39: TLabel;
Label40: TLabel;
Label41: TLabel;
Button14: TButton;
Button15: TButton;
Label42: TLabel;
Label43: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
procedure Button11Click(Sender: TObject);
procedure Button12Click(Sender: TObject);
procedure BStartClick(Sender: TObject);
procedure Button13MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button14Click(Sender: TObject);
procedure Button15Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
loc,wag,wag2,wag3:TMoverParameters;
mechanik: TController;
pociag: TTrainParameters;
l0,l1,l2,l3:TLocation;
r0,r1,r2,r3:TRotation;
Shape:TTrackShape; Track:TTrackParam;
ExternalVoltage:real;
ActualTime:real;
fout: text;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
assignfile(fout,'log.dat');
rewrite(fout);
ActualTime:=0;
loc:=TMoverParameters.Create;
wag:=TMoverParameters.Create;
wag2:=TMoverParameters.Create;
wag3:=TMoverParameters.Create;
mechanik:=TController.Create;
pociag:=TTrainParameters.Create;
Shape.R:=0; Shape.Len:=10000; Shape.dHtrack:=0; Shape.dHrail:=0;
Track.Width:=1435; Track.friction:=0.15; Track.CategoryFlag:=1;
Track.QualityFlag:=25; Track.DamageFlag:=0;
Track.VelMax:=120;
ExternalVoltage:=3000;
l0.x:=0; l0.y:=0; l0.z:=0;
l1.x:=-14.0235; l1.y:=0; l1.z:=0;
l2.x:=-27.3634; l2.y:=0; l2.z:=0;
l3.x:=-40.7032; l3.y:=0; l3.z:=0;
r0.rx:=0; r0.ry:=0; r0.rz:=0;
r1.rx:=0; r1.ry:=0; r1.rz:=0;
r2.rx:=0; r2.ry:=0; r2.rz:=0;
r3.rx:=0; r3.ry:=0; r3.rz:=0;
{ loc.Init(l1,r1,0,'en57','456',0,'Human',1); }
loc.Init(l0,r0,60,'eu07','456',0,'',1);
wag.Init(l1,r1,60,'Falns_440v','52-51-342027-2',30,'',0);
wag2.Init(l2,r2,60,'Falns_440v','52-51-322311-5',30,'',0);
wag3.Init(l3,r3,60,'Falns_440v','52-51-410025-3',30,'',0);
pociag.init('Testowy Express',100);
mechanik.init(l1,r1,True,@loc,@pociag,Aggressive);
if (loc.loadchkfile('') and wag.loadchkfile('') and wag2.loadchkfile('') and wag3.loadchkfile(''))
and (loc.CheckLocomotiveParameters(Go) and wag.CheckLocomotiveParameters(Go) and wag2.CheckLocomotiveParameters(Go) and wag3.CheckLocomotiveParameters(Go)) then
begin
Label1.Caption:='OK';
loc.attach(2,@wag,3);
wag.attach(1,@loc,3);
wag.attach(2,@wag2,3);
wag2.attach(1,@wag,3);
wag2.attach(2,@wag3,3);
wag3.attach(1,@wag2,3);
Timer1.Enabled:=True;
end
else Label1.Caption:=inttostr(conversionerror)+' '+inttostr(linecount);
Button1.Visible:=False;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if Timer1.Enabled then
begin
Timer1.Enabled:=False;
CloseFile(fout);
end;
loc.Free;
wag.Free;
wag2.free;
wag3.free;
mechanik.free;
Close;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var dl,dt:real;
begin
dt:=Timer1.Interval/1000;
ActualTime:=ActualTime+dt;
loc.ComputeTotalForce(dt,Shape,Track,ExternalVoltage);
wag.ComputeTotalForce(dt,Shape,Track,ExternalVoltage);
wag2.ComputeTotalForce(dt,Shape,Track,ExternalVoltage);
wag3.ComputeTotalForce(dt,Shape,Track,ExternalVoltage);
dl:=loc.ComputeMovement(dt,Shape,Track,ExternalVoltage,l0,r0);
l0.x:=l0.x+dl;
dl:=wag.ComputeMovement(dt,Shape,Track,ExternalVoltage,l1,r1);
l1.x:=l1.x+dl;
dl:=wag2.ComputeMovement(dt,Shape,Track,ExternalVoltage,l2,r2);
l2.x:=l2.x+dl;
dl:=wag3.ComputeMovement(dt,Shape,Track,ExternalVoltage,l3,r3);
l3.x:=l3.x+dl;
if l0.x<500 then mechanik.UpdateSituation(500-l0.x,dt)
else
if l0.x<2500 then mechanik.UpdateSituation(-1,dt)
else
if l0.x<3500 then mechanik.UpdateSituation(3500-l0.x,dt);
if (l0.x>499) and (l0.x<505) then
mechanik.SetVelocity(-1,-1,0);
if (l0.x>2499) and (l0.x<2510) then
mechanik.SetVelocity(-1,0,0);
Label2.Caption:=r2s(Loc.Im,0)+' A';
Label3.Caption:=r2s(Loc.Ft/1000,0)+' kN';
Label4.Caption:=r2s(l0.x,0)+' m';
Label5.Caption:=r2s(Sign(Loc.V)*Loc.Vel,0)+' km/h';
Label6.Caption:=r2s(Loc.AccS,0)+' m/ss';
Label7.Caption:=r2s(Loc.couplers[1].cforce/1000,0)+' kN';
Label8.Caption:=r2s(Loc.couplers[2].cforce/1000,0)+' kN';
Label9.Caption:=r2s(Loc.Fb/1000,0)+' kN';
Label10.Caption:=r2s(Loc.Compressor,0)+' MPa';
Label11.Caption:=r2s(Loc.PipePress,0)+' MPa';
Label12.Caption:=r2s(Loc.BrakePress,0)+' MPa';
Label13.Caption:=IntToStr(Loc.MainCtrlPos);
Label14.Caption:=IntToStr(Loc.BrakeCtrlPos);
Label15.Caption:=IntToStr(Loc.LocalBrakePos);
Label16.Caption:=IntToStr(Loc.showcurrent(1));
Label17.Caption:=IntToStr(Loc.showcurrent(2));
Label18.Caption:=IntToStr(Loc.ScndCtrlPos);
if loc.SlippingWheels then
Label19.Caption:='Poslizg!'
else Label19.Caption:=' ';
Label20.Caption:=IntToStr(Loc.MainCtrlActualPos);
Label21.Caption:=IntToStr(Loc.ScndCtrlActualPos);
Label22.Caption:=r2s(l1.x,0)+' m';
Label23.Caption:=r2s(Sign(wag.V)*wag.Vel,0)+' km/h';
Label24.Caption:=r2s(Distance(loc.loc,wag.loc,loc.dim,wag.dim),0)+' m';
Label25.Caption:=r2s(loc.nrot,0)+' 1/s';
Label26.Caption:=r2s(wag.couplers[1].cforce/1000,0)+' kN';
Label27.Caption:=r2s(wag.couplers[2].cforce/1000,0)+' kN';
Label28.Caption:=r2s(l2.x,0)+' m';
Label29.Caption:=r2s(sign(wag2.V)*wag2.Vel,0)+' km/h';
Label30.Caption:=r2s(loc.dpLocalValve/dt,0)+' MPa/s';
Label31.Caption:=r2s(loc.dpBrake/dt,0)+' MPa/s';
Label32.Caption:=r2s(loc.dpMainValve/dt,0)+' MPa/s';
Label33.Caption:=r2s(loc.dpPipe/dt,0)+' MPa/s';
Label34.Caption:=r2s(wag2.PipePress,0)+' MPa';
Label35.Caption:=r2s(l3.x,0)+' m';
Label36.Caption:=r2s(sign(wag3.V)*wag3.Vel,0)+' km/h';
Label37.Caption:=r2s(wag3.couplers[1].cforce/1000,0)+' kN';
Label38.Caption:=r2s(wag3.brakepress,0)+' MPa';
Label39.Caption:=r2s(loc.enginePower/1000,0)+' kW';
Label40.Caption:=i2s(trunc(loc.Rventrot*60))+' /min';
Label41.Visible:=loc.SandDose;
Label42.Caption:=r2s(mechanik.accdesired,0)+' m/ss';
Label43.Caption:=r2s(mechanik.veldesired,0)+' km/h';
Lczas.Caption:=r2s(actualtime,0)+' s';
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled:=False;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
loc.incbrakelevel(1);
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
loc.decbrakelevel(1);
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
loc.inclocalbrakelevel(1);
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
loc.declocalbrakelevel(1);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
loc.incmainctrl(1);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
loc.decmainctrl(1);
end;
procedure TForm1.Button9Click(Sender: TObject);
begin
loc.DirectionForward;
end;
procedure TForm1.Button10Click(Sender: TObject);
begin
loc.DirectionBackward;
end;
procedure TForm1.Button11Click(Sender: TObject);
begin
loc.FuseOn;
end;
procedure TForm1.Button12Click(Sender: TObject);
begin
Loc.AntiSlippingBrake;
end;
procedure TForm1.BStartClick(Sender: TObject);
begin
loc.activedir:=1;
{ if mechanik.OrderDirectionChange(1) then }
mechanik.SetVelocity(60,0,0);
end;
procedure TForm1.Button13MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
loc.SandDoseOn;
end;
procedure TForm1.Button14Click(Sender: TObject);
begin
mechanik.SetVelocity(30,120,0);
end;
procedure TForm1.Button15Click(Sender: TObject);
begin
mechanik.SetVelocity(0,120,0);
end;
end.

182
MdlMngr.cpp Normal file
View File

@@ -0,0 +1,182 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include "system.hpp"
#include "classes.hpp"
#include "Texture.h"
#pragma hdrstop
#include "MdlMngr.h"
#include "Globals.h"
#define SeekFiles AnsiString("*.t3d")
TModel3d* __fastcall TMdlContainer::LoadModel(char *newName,bool dynamic)
{//wczytanie modelu do kontenerka
SafeDeleteArray(Name);
SafeDelete(Model);
Name=new char[strlen(newName)+1];
strcpy(Name,newName);
Model=new TModel3d();
if (!Model->LoadFromFile(Name,dynamic)) //np. "models\\pkp/head1-y.t3d"
SafeDelete(Model);
return Model;
};
TMdlContainer *TModelsManager::Models;
int TModelsManager::Count;
const MAX_MODELS=1000;
void __fastcall TModelsManager::Init()
{
Models=new TMdlContainer[MAX_MODELS];
Count=0;
}
/*
__fastcall TModelsManager::TModelsManager()
{
// Models= NULL;
Models= new TMdlContainer[MAX_MODELS];
Count= 0;
};
__fastcall TModelsManager::~TModelsManager()
{
Free();
};
*/
void __fastcall TModelsManager::Free()
{
SafeDeleteArray(Models);
}
TModel3d* __fastcall TModelsManager::LoadModel(char *Name,bool dynamic)
{//wczytanie modelu do tablicy
TModel3d *mdl=NULL;
if (Count>=MAX_MODELS)
Error("FIXME: Too many models, program will now crash :)");
else
{
mdl=Models[Count].LoadModel(Name,dynamic);
if (mdl) Count++; //jeśli błąd wczytania modelu, to go nie wliczamy
}
return mdl;
}
TModel3d* __fastcall TModelsManager::GetModel(const char *Name,bool dynamic)
{//model może być we wpisie "node...model" albo "node...dynamic", a także być dodatkowym w dynamic (kabina, wnętrze, ładunek)
//dla "node...dynamic" mamy podaną ścieżkę w "\dynamic\" i musi być co najmniej 1 poziom, zwkle są 2
//dla "node...model" może być typowy model statyczny ze ścieżką, domyślnie w "\scenery\" albo "\models"
//albo może być model z "\dynamic\", jeśli potrzebujemy wstawić auto czy wagon nieruchomo
// - ze ścieżki z której jest wywołany, np. dir="scenery\bud\" albo dir="dynamic\pkp\st44_v1\" plus name="model.t3d"
// - z domyślnej ścieżki dla modeli, np. "scenery\" albo "models\" plus name="bud\dombale.t3d" (dir="")
// - konkretnie podanej ścieżki np. name="\scenery\bud\dombale.t3d" (dir="")
//wywołania:
// - konwersja wszystkiego do E3D, podawana dokładna ścieżka, tekstury tam, gdzie plik
// - wczytanie kabiny, dokładna ścieżka, tekstury z katalogu modelu
// - wczytanie ładunku, ścieżka dokładna, tekstury z katalogu modelu
// - wczytanie modelu, ścieżka dokładna, tekstury z katalogu modelu
// - wczytanie przedsionków, ścieżka dokładna, tekstury z katalogu modelu
// - wczytanie uproszczonego wnętrza, ścieżka dokładna, tekstury z katalogu modelu
// - niebo animowane, ścieżka brana ze wpisu, tekstury nieokreślone
// - wczytanie modelu animowanego - Init() - sprawdzić
char buf[255];
AnsiString buftp=Global::asCurrentTexturePath; //zapamiętanie aktualnej ścieżki do tekstur, bo będzie tyczmasowo zmieniana
/*
// Ra: niby tak jest lepiej, ale działa gorzej, więc przywrócone jest oryginalne
//nawet jeśli model będzie pobrany z tablicy, to trzeba ustalić ścieżkę dla tekstur
if (dynamic) //na razie tak, bo nie wiadomo, jaki może mieć wpływ na pozostałe modele
{//dla pojazdów podana jest zawsze pełna ścieżka do modelu
strcpy(buf,Name);
if (strchr(Name,'/')!=NULL)
{//pobieranie tekstur z katalogu, w którym jest model
Global::asCurrentTexturePath=Global::asCurrentTexturePath+AnsiString(Name);
Global::asCurrentTexturePath.Delete(Global::asCurrentTexturePath.Pos("/")+1,Global::asCurrentTexturePath.Length());
}
}
else
{//dla modeli scenerii trzeba ustalić ścieżkę
if (strchr(Name,'\\')==NULL)
{//jeśli nie ma lewego ukośnika w ścieżce, a jest prawy, to zmienić ścieżkę dla tekstur na tę z modelem
strcpy(buf,"models\\"); //Ra: było by lepiej katalog dodać w parserze
//strcpy(buf,"scenery\\"); //Ra: było by lepiej katalog dodać w parserze
strcat(buf,Name);
if (strchr(Name,'/')!=NULL)
{//jeszcze musi być prawy ukośnik
Global::asCurrentTexturePath=Global::asCurrentTexturePath+AnsiString(Name);
Global::asCurrentTexturePath.Delete(Global::asCurrentTexturePath.Pos("/")+1,Global::asCurrentTexturePath.Length());
}
}
else
{//jeśli jest lewy ukośnik, to ścieżkę do tekstur zmienić tylko dla pojazdów
strcpy(buf,Name);
}
}
StrLower(buf);
for (int i=0;i<Count;i++)
{//bezsensowne przeszukanie tabeli na okoliczność wystąpienia modelu
if (strcmp(buf,Models[i].Name)==0)
{
Global::asCurrentTexturePath=buftp; //odtworzenie ścieżki do tekstur
return (Models[i].Model); //model znaleziony
}
};
*/
if (strchr(Name,'\\')==NULL)
{
strcpy(buf,"models\\"); //Ra: było by lepiej katalog dodać w parserze
strcat(buf,Name);
if (strchr(Name,'/')!=NULL)
{
Global::asCurrentTexturePath= Global::asCurrentTexturePath+AnsiString(Name);
Global::asCurrentTexturePath.Delete(Global::asCurrentTexturePath.Pos("/")+1,Global::asCurrentTexturePath.Length());
}
}
else
{strcpy(buf,Name);
if (dynamic) //na razie tak, bo nie wiadomo, jaki może mieć wpływ na pozostałe modele
if (strchr(Name,'/')!=NULL)
{//pobieranie tekstur z katalogu, w którym jest model
Global::asCurrentTexturePath= Global::asCurrentTexturePath+AnsiString(Name);
Global::asCurrentTexturePath.Delete(Global::asCurrentTexturePath.Pos("/")+1,Global::asCurrentTexturePath.Length());
}
}
StrLower(buf);
for (int i=0; i<Count; i++)
{
if (strcmp(buf,Models[i].Name)==0)
{
Global::asCurrentTexturePath= buftp;
return (Models[i].Model);
}
};
TModel3d* tmpModel=LoadModel(buf,dynamic); //model nie znaleziony, to wczytać
Global::asCurrentTexturePath=buftp; //odtworzenie ścieżki do tekstur
return (tmpModel); //NULL jeśli błąd
};
/*
TModel3d __fastcall TModelsManager::GetModel(char *Name, AnsiString asReplacableTexture)
{
GLuint ReplacableTextureID= 0;
TModel3d NewModel;
NewModel= *GetNextModel(Name);
if (asReplacableTexture!=AnsiString("none"))
ReplacableTextureID= TTexturesManager::GetTextureID(asReplacableTexture.c_str());
NewModel.ReplacableSkinID=ReplacableTextureID;
return NewModel;
};
*/
//---------------------------------------------------------------------------
#pragma package(smart_init)

34
MdlMngr.h Normal file
View File

@@ -0,0 +1,34 @@
//---------------------------------------------------------------------------
#ifndef MdlMngrH
#define MdlMngrH
#include "Model3d.h"
#include "usefull.h"
class TMdlContainer
{
friend class TModelsManager;
__fastcall TMdlContainer() { Name= NULL; Model= NULL; };
__fastcall ~TMdlContainer() { SafeDeleteArray(Name); SafeDelete(Model); };
TModel3d* __fastcall LoadModel(char *newName,bool dynamic);
TModel3d *Model;
char *Name;
};
class TModelsManager
{//klasa statyczna, nie ma obiektu
private:
static TMdlContainer *Models;
static int Count;
static TModel3d* __fastcall LoadModel(char *Name,bool dynamic);
public:
// __fastcall TModelsManager();
// __fastcall ~TModelsManager();
static void __fastcall Init();
static void __fastcall Free();
//McZapkie: dodalem sciezke, notabene Path!=Patch :)
static TModel3d* __fastcall GetModel(const char *Name,bool dynamic=false);
};
//---------------------------------------------------------------------------
#endif

176
MemCell.cpp Normal file
View File

@@ -0,0 +1,176 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Driver.h"
#include "mctools.hpp"
#include "MemCell.h"
#include "Event.h"
#include "parser.h"
#include "Usefull.h"
#include "Globals.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TMemCell::TMemCell(vector3 *p)
{
fValue1=fValue2=0;
szText=new char[256]; //musi byæ dla automatycznie tworzonych komórek dla odcinków izolowanych
vPosition=p?*p:vector3(0,0,0); //ustawienie wspó³rzêdnych, bo do TGroundNode nie ma dostêpu
bCommand=false; //komenda wys³ana
OnSent=NULL;
}
__fastcall TMemCell::~TMemCell()
{
SafeDeleteArray(szText);
}
void __fastcall TMemCell::Init()
{
}
void __fastcall TMemCell::UpdateValues(char *szNewText, double fNewValue1, double fNewValue2, int CheckMask)
{
if (CheckMask&update_memadd)
{//dodawanie wartoœci
if (TestFlag(CheckMask,update_memstring))
strcat(szText,szNewText);
if (TestFlag(CheckMask,update_memval1))
fValue1+=fNewValue1;
if (TestFlag(CheckMask,update_memval2))
fValue2+=fNewValue2;
}
else
{
if (TestFlag(CheckMask,update_memstring))
strcpy(szText,szNewText);
if (TestFlag(CheckMask,update_memval1))
fValue1=fNewValue1;
if (TestFlag(CheckMask,update_memval2))
fValue2=fNewValue2;
}
if (TestFlag(CheckMask,update_memstring))
CommandCheck();//jeœli zmieniony tekst, próbujemy rozpoznaæ komendê
}
TCommandType __fastcall TMemCell::CommandCheck()
{//rozpoznanie komendy
if (strcmp(szText,"SetVelocity")==0) //najpopularniejsze
{eCommand=cm_SetVelocity;
bCommand=false; //ta komenda nie jest wysy³ana
}
else if (strcmp(szText,"ShuntVelocity")==0) //w tarczach manewrowych
{eCommand=cm_ShuntVelocity;
bCommand=false; //ta komenda nie jest wysy³ana
}
else if (strcmp(szText,"Change_direction")==0) //zdarza siê
{eCommand=cm_ChangeDirection;
bCommand=true; //do wys³ania
}
else if (strcmp(szText,"OutsideStation")==0) //zdarza siê
{eCommand=cm_OutsideStation;
bCommand=false; //tego nie powinno byæ w komórce
}
else if (strncmp(szText,"PassengerStopPoint:",19)==0) //porównanie pocz¹tków
{eCommand=cm_PassengerStopPoint;
bCommand=false; //tego nie powinno byæ w komórce
}
else if (strcmp(szText,"SetProximityVelocity")==0) //nie powinno tego byæ
{eCommand=cm_SetProximityVelocity;
bCommand=false; //ta komenda nie jest wysy³ana
}
else
{eCommand=cm_Unknown; //ci¹g nierozpoznany (nie jest komend¹)
bCommand=true; //do wys³ania
}
return eCommand;
}
bool __fastcall TMemCell::Load(cParser *parser)
{
std::string token;
parser->getTokens(1,false); //case sensitive
*parser >> token;
SafeDeleteArray(szText);
szText=new char[256]; //musi byæ bufor do ³¹czenia tekstów
strcpy(szText,token.c_str());
parser->getTokens();
*parser >> fValue1;
parser->getTokens();
*parser >> fValue2;
parser->getTokens();
*parser >> token;
if (token.compare("none")!=0) //gdy ró¿ne od "none"
asTrackName=AnsiString(token.c_str()); //sprawdzane przez IsEmpty()
parser->getTokens();
*parser >> token;
if (token.compare("endmemcell")!=0)
Error("endmemcell statement missing");
CommandCheck();
return true;
}
void __fastcall TMemCell::PutCommand(TController *Mech, vector3 *Loc)
{//wys³anie zawartoœci komórki do AI
if (Mech)
Mech->PutCommand(szText,fValue1,fValue2,Loc);
}
bool __fastcall TMemCell::Compare(char *szTestText,double fTestValue1,double fTestValue2,int CheckMask)
{//porównanie zawartoœci komórki pamiêci z podanymi wartoœciami
if (TestFlag(CheckMask,conditional_memstring))
{//porównaæ teksty
char *pos=StrPos(szTestText,"*"); //zwraca wskaŸnik na pozycjê albo NULL
if (pos)
{//porównanie fragmentu ³añcucha
int i=pos-szTestText; //iloœæ porównywanych znaków
if (i) //jeœli nie jest pierwszym znakiem
if (AnsiString(szTestText,i)!=AnsiString(szText,i))
return false; //pocz¹tki o d³ugoœci (i) s¹ ró¿ne
}
else
if (AnsiString(szTestText)!=AnsiString(szText))
return false; //³¹ñcuchy s¹ ró¿ne
}
//tekst zgodny, porównaæ resztê
return ((!TestFlag(CheckMask,conditional_memval1) || (fValue1==fTestValue1)) &&
(!TestFlag(CheckMask,conditional_memval2) || (fValue2==fTestValue2)));
};
bool __fastcall TMemCell::Render()
{
return true;
}
bool __fastcall TMemCell::IsVelocity()
{//sprawdzenie, czy event odczytu tej komórki ma byæ do skanowania, czy do kolejkowania
if (eCommand==cm_SetVelocity) return true;
if (eCommand==cm_ShuntVelocity) return true;
return (eCommand==cm_SetProximityVelocity);
};
void __fastcall TMemCell::StopCommandSent()
{//
if (!bCommand) return;
bCommand=false;
if (OnSent) //jeœli jest event
Global::AddToQuery(OnSent,NULL);
};
void __fastcall TMemCell::AssignEvents(TEvent *e)
{//powi¹zanie eventu
OnSent=e;
};

43
MemCell.h Normal file
View File

@@ -0,0 +1,43 @@
//---------------------------------------------------------------------------
#ifndef MemCellH
#define MemCellH
#include "Classes.h"
#include "dumb3d.h"
using namespace Math3D;
class TMemCell
{
private:
vector3 vPosition;
char *szText;
double fValue1;
double fValue2;
TCommandType eCommand;
bool bCommand; //czy zawiera komendê dla zatrzymanego AI
TEvent *OnSent; //event dodawany do kolejki po wys³aniu komendy zatrzymuj¹cej sk³ad
public:
AnsiString asTrackName; //McZapkie-100302 - zeby nazwe toru na ktory jest Putcommand wysylane pamietac
__fastcall TMemCell(vector3 *p);
__fastcall ~TMemCell();
void __fastcall Init();
void __fastcall UpdateValues(char *szNewText, double fNewValue1, double fNewValue2, int CheckMask);
bool __fastcall Load(cParser *parser);
void __fastcall PutCommand(TController *Mech, vector3 *Loc);
bool __fastcall Compare(char *szTestText, double fTestValue1, double fTestValue2, int CheckMask);
bool __fastcall Render();
inline char* __fastcall Text() {return szText;};
inline double __fastcall Value1() {return fValue1;};
inline double __fastcall Value2() {return fValue2;};
inline vector3 __fastcall Position() {return vPosition;};
inline TCommandType __fastcall Command() {return eCommand;};
inline bool __fastcall StopCommand() {return bCommand;};
void __fastcall StopCommandSent();
TCommandType __fastcall CommandCheck();
bool __fastcall IsVelocity();
void __fastcall AssignEvents(TEvent *e);
};
//---------------------------------------------------------------------------
#endif

2077
Model3d.cpp Normal file

File diff suppressed because it is too large Load Diff

365
Model3d.h Normal file
View File

@@ -0,0 +1,365 @@
//---------------------------------------------------------------------------
#ifndef Model3dH
#define Model3dH
#include "opengl/glew.h"
#include "Parser.h"
#include "dumb3d.h"
using namespace Math3D;
#include "Float3d.h"
#include "VBO.h"
struct GLVERTEX
{
vector3 Point;
vector3 Normal;
float tu,tv;
};
class TStringPack
{
char *data;
//+0 - 4 bajty: typ kromki
//+4 - 4 bajty: długość łącznie z nagłówkiem
//+8 - obszar łańcuchów znakowych, każdy zakończony zerem
int *index;
//+0 - 4 bajty: typ kromki
//+4 - 4 bajty: długość łącznie z nagłówkiem
//+8 - tabela indeksów
public:
char* String(int n);
char* StringAt(int n) {return data+9+n;};
__fastcall TStringPack() {data=NULL; index=NULL;};
void __fastcall Init(char *d) {data=d;};
void __fastcall InitIndex(int *i) {index=i;};
};
class TMaterialColor
{
public:
__fastcall TMaterialColor() {};
__fastcall TMaterialColor(char V)
{
r=g=b=V;
};
// __fastcall TMaterialColor(double R, double G, double B)
__fastcall TMaterialColor(char R, char G, char B)
{
r=R; g=G; b=B;
};
char r,g,b;
};
/*
struct TMaterial
{
int ID;
AnsiString Name;
//McZapkie-240702: lepiej uzywac wartosci float do opisu koloru bo funkcje opengl chyba tego na ogol uzywaja
float Ambient[4];
float Diffuse[4];
float Specular[4];
float Transparency;
GLuint TextureID;
};
*/
/*
struct THitBoxContainer
{
TPlane Planes[6];
int Index;
inline void __fastcall Reset() { Planes[0]= TPlane(vector3(0,0,0),0.0f); };
inline bool __fastcall Inside(vector3 Point)
{
bool Hit= true;
if (Planes[0].Defined())
for (int i=0; i<6; i++)
{
if (Planes[i].GetSide(Point)>0)
{
Hit= false;
break;
};
}
else return(false);
return(Hit);
};
};
*/
/* Ra: tego nie będziemy już używać, bo można wycisnąć więcej
typedef enum
{smt_Unknown, //nieznany
smt_Mesh, //siatka
smt_Point,
smt_FreeSpotLight, //punkt świetlny
smt_Text, //generator tekstu
smt_Stars //wiele punktów świetlnych
} TSubModelType;
*/
//Ra: specjalne typy submodeli, poza tym GL_TRIANGLES itp.
const int TP_ROTATOR=256;
const int TP_FREESPOTLIGHT=257;
const int TP_STARS=258;
const int TP_TEXT=259;
enum TAnimType //rodzaj animacji
{at_None, //brak
at_Rotate, //obrót względem wektora o kąt
at_RotateXYZ, //obrót względem osi o kąty
at_Translate, //przesunięcie
at_SecondsJump, //sekundy z przeskokiem
at_MinutesJump, //minuty z przeskokiem
at_HoursJump, //godziny z przeskokiem 12h/360°
at_Hours24Jump, //godziny z przeskokiem 24h/360°
at_Seconds, //sekundy płynnie
at_Minutes, //minuty płynnie
at_Hours, //godziny płynnie 12h/360°
at_Hours24, //godziny płynnie 24h/360°
at_Billboard, //obrót w pionie do kamery
at_Wind, //ruch pod wpływem wiatru
at_Sky, //animacja nieba
at_IK=0x100, //odwrotna kinematyka - submodel sterujący (np. staw skokowy)
at_IK11=0x101, //odwrotna kinematyka - submodel nadrzędny do sterowango (np. stopa)
at_IK21=0x102, //odwrotna kinematyka - submodel nadrzędny do sterowango (np. podudzie)
at_IK22=0x103, //odwrotna kinematyka - submodel nadrzędny do nadrzędnego sterowango (np. udo)
at_Digital=0x200, //dziesięciocyfrowy licznik mechaniczny (z cylindrami)
at_DigiClk=0x201, //zegar cyfrowy jako licznik na dziesięciościanach
at_Undefined=0x800000FF //animacja chwilowo nieokreślona
};
class TModel3d;
class TSubModelInfo;
class TSubModel
{//klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
//Ra: ta klasa ma mieć wielkość 256 bajtów, aby pokryła się z formatem binarnym
//Ra: nie przestawiać zmiennych, bo wczytują się z pliku binarnego!
private:
TSubModel *Next;
TSubModel *Child;
int eType; //Ra: modele binarne dają więcej możliwości niż mesh złożony z trójkątów
int iName; //numer łańcucha z nazwą submodelu, albo -1 gdy anonimowy
public: //chwilowo
TAnimType b_Anim;
private:
int iFlags; //flagi informacyjne:
//bit 0: =1 faza rysowania zależy od wymiennej tekstury 0
//bit 1: =1 faza rysowania zależy od wymiennej tekstury 1
//bit 2: =1 faza rysowania zależy od wymiennej tekstury 2
//bit 3: =1 faza rysowania zależy od wymiennej tekstury 3
//bit 4: =1 rysowany w fazie nieprzezroczystych (stała tekstura albo brak)
//bit 5: =1 rysowany w fazie przezroczystych (stała tekstura)
//bit 7: =1 ta sama tekstura, co poprzedni albo nadrzędny
//bit 8: =1 wierzchołki wyświetlane z indeksów
//bit 9: =1 wczytano z pliku tekstowego (jest właścicielem tablic)
//bit 13: =1 wystarczy przesunięcie zamiast mnożenia macierzy (trzy jedynki)
//bit 14: =1 wymagane przechowanie macierzy (animacje)
//bit 15: =1 wymagane przechowanie macierzy (transform niejedynkowy)
union
{//transform, nie każdy submodel musi mieć
float4x4 *fMatrix; //pojedyncza precyzja wystarcza
//matrix4x4 *dMatrix; //do testu macierz podwójnej precyzji
int iMatrix; //w pliku binarnym jest numer matrycy
};
int iNumVerts; //ilość wierzchołków (1 dla FreeSpotLight)
int iVboPtr; //początek na liście wierzchołków albo indeksów
int iTexture; //numer nazwy tekstury, -1 wymienna, 0 brak
float fVisible; //próg jasności światła do załączenia submodelu
float fLight; //próg jasności światła do zadziałania selfillum
float f4Ambient[4];
float f4Diffuse[4]; //float ze względu na glMaterialfv()
float f4Specular[4];
float f4Emision[4];
float fWireSize; //nie używane, ale wczytywane
float fSquareMaxDist;
float fSquareMinDist;
//McZapkie-050702: parametry dla swiatla:
float fNearAttenStart;
float fNearAttenEnd;
int bUseNearAtten; //te 3 zmienne okreslaja rysowanie aureoli wokol zrodla swiatla
int iFarAttenDecay; //ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R)
float fFarDecayRadius; //normalizacja j.w.
float fCosFalloffAngle; //cosinus kąta stożka pod którym widać światło
float fCosHotspotAngle; //cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
float fCosViewAngle; //cos kata pod jakim sie teraz patrzy
//Ra: dalej są zmienne robocze, można je przestawiać z zachowaniem rozmiaru klasy
int TextureID; //numer tekstury, -1 wymienna, 0 brak
int bWire; //nie używane, ale wczytywane
//short TexAlpha; //Ra: nie używane już
GLuint uiDisplayList; //roboczy numer listy wyświetlania
float Opacity; //nie używane, ale wczytywane
//ABu: te same zmienne, ale zdublowane dla Render i RenderAlpha,
//bo sie chrzanilo przemieszczanie obiektow.
//Ra: już się nie chrzani
float f_Angle;
float3 v_RotateAxis;
float3 v_Angles;
public: //chwilowo
float3 v_TransVector;
float8 *Vertices; //roboczy wskaźnik - wczytanie T3D do VBO
int iAnimOwner; //roboczy numer egzemplarza, który ustawił animację
TAnimType b_aAnim; //kody animacji oddzielnie, bo zerowane
public:
float4x4 *mAnimMatrix; //macierz do animacji kwaternionowych (należy do AnimContainer)
char space[8]; //wolne miejsce na przyszłe zmienne (zmniejszyć w miarę potrzeby)
public:
TSubModel **smLetter; //wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
TSubModel *Parent; //nadrzędny, np. do wymnażania macierzy
int iVisible; //roboczy stan widoczności
//AnsiString asTexture; //robocza nazwa tekstury do zapisania w pliku binarnym
//AnsiString asName; //robocza nazwa
char *pTexture; //robocza nazwa tekstury do zapisania w pliku binarnym
char *pName; //robocza nazwa
private:
//int __fastcall SeekFaceNormal(DWORD *Masks, int f,DWORD dwMask,vector3 *pt,GLVERTEX *Vertices);
int __fastcall SeekFaceNormal(DWORD *Masks,int f,DWORD dwMask,float3 *pt,float8 *Vertices);
void __fastcall RaAnimation(TAnimType a);
public:
static int iInstance; //identyfikator egzemplarza, który aktualnie renderuje model
static GLuint *ReplacableSkinId;
static int iAlpha; //maska bitowa dla danego przebiegu
static double fSquareDist;
static TModel3d* pRoot;
static AnsiString* pasText; //tekst dla wyświetlacza (!!!! do przemyślenia)
__fastcall TSubModel();
__fastcall ~TSubModel();
void __fastcall FirstInit();
int __fastcall Load(cParser& Parser, TModel3d *Model,int Pos,bool dynamic);
void __fastcall ChildAdd(TSubModel *SubModel);
void __fastcall NextAdd(TSubModel *SubModel);
TSubModel* __fastcall NextGet() {return Next;};
TSubModel* __fastcall ChildGet() {return Child;};
int __fastcall TriangleAdd(TModel3d *m,int tex,int tri);
float8* __fastcall TrianglePtr(int tex,int pos,int *la,int *ld,int*ls);
//float8* __fastcall TrianglePtr(const char *tex,int tri);
//void __fastcall SetRotate(vector3 vNewRotateAxis,float fNewAngle);
void __fastcall SetRotate(float3 vNewRotateAxis,float fNewAngle);
void __fastcall SetRotateXYZ(vector3 vNewAngles);
void __fastcall SetRotateXYZ(float3 vNewAngles);
void __fastcall SetTranslate(vector3 vNewTransVector);
void __fastcall SetTranslate(float3 vNewTransVector);
void __fastcall SetRotateIK1(float3 vNewAngles);
TSubModel* __fastcall GetFromName(AnsiString search,bool i=true);
TSubModel* __fastcall GetFromName(char *search,bool i=true);
void __fastcall RenderDL();
void __fastcall RenderAlphaDL();
void __fastcall RenderVBO();
void __fastcall RenderAlphaVBO();
//inline matrix4x4* __fastcall GetMatrix() {return dMatrix;};
inline float4x4* __fastcall GetMatrix() {return fMatrix;};
//matrix4x4* __fastcall GetTransform() {return Matrix;};
inline void __fastcall Hide() {iVisible=0;};
void __fastcall RaArrayFill(CVertNormTex *Vert);
//void __fastcall Render();
int __fastcall FlagsCheck();
void __fastcall WillBeAnimated() {if (this) iFlags|=0x4000;};
void __fastcall InitialRotate(bool doit);
void __fastcall DisplayLists();
void __fastcall Info();
void __fastcall InfoSet(TSubModelInfo *info);
void __fastcall BinInit(TSubModel *s,float4x4 *m,float8 *v,TStringPack *t,TStringPack *n=NULL,bool dynamic=false);
void __fastcall ReplacableSet(GLuint *r,int a)
{ReplacableSkinId=r; iAlpha=a;};
void __fastcall TextureNameSet(const char *n);
void __fastcall NameSet(const char *n);
//Ra: funkcje do budowania terenu z E3D
int __fastcall Flags() {return iFlags;};
void __fastcall UnFlagNext() {iFlags&=0x00FFFFFF;};
void __fastcall ColorsSet(int *a,int *d,int*s);
inline float3 Translation1Get()
{return fMatrix?*(fMatrix->TranslationGet())+v_TransVector:v_TransVector;}
inline float3 Translation2Get()
{return *(fMatrix->TranslationGet())+Child->Translation1Get();}
void __fastcall ParentMatrix(float4x4 *m);
float __fastcall MaxY(const float4x4 &m);
void __fastcall AdjustDist();
};
class TSubModelInfo
{//klasa z informacjami o submodelach, do tworzenia pliku binarnego
public:
TSubModel *pSubModel; //wskaźnik na submodel
int iTransform; //numer transformu (-1 gdy brak)
int iName; //numer nazwy
int iTexture; //numer tekstury
int iNameLen; //długość nazwy
int iTextureLen; //długość tekstury
int iNext,iChild; //numer następnego i potomnego
static int iTotalTransforms; //ilość transformów
static int iTotalNames; //ilość nazw
static int iTotalTextures; //ilość tekstur
static int iCurrent; //aktualny obiekt
static TSubModelInfo* pTable; //tabele obiektów pomocniczych
__fastcall TSubModelInfo()
{pSubModel=NULL;
iTransform=iName=iTexture=iNext=iChild=-1; //nie ma
iNameLen=iTextureLen=0;
}
void __fastcall Reset()
{pTable=this; //ustawienie wskaźnika tabeli obiektów
iTotalTransforms=iTotalNames=iTotalTextures=iCurrent=0; //zerowanie liczników
}
__fastcall ~TSubModelInfo() {};
};
class TModel3d : public CMesh
{
private:
//TMaterial *Materials;
//int MaterialsCount; //Ra: nie używane
//bool TractionPart; //Ra: nie używane
TSubModel *Root; //drzewo submodeli
int iFlags; //Ra: czy submodele mają przezroczyste tekstury
public: //Ra: tymczasowo
int iNumVerts; //ilość wierzchołków (gdy nie ma VBO, to m_nVertexCount=0)
private:
TStringPack Textures; //nazwy tekstur
TStringPack Names; //nazwy submodeli
int *iModel; //zawartość pliku binarnego
int iSubModelsCount; //Ra: używane do tworzenia binarnych
AnsiString asBinary; //nazwa pod którą zapisać model binarny
public:
inline TSubModel* __fastcall GetSMRoot() {return(Root);};
//double Radius; //Ra: nie używane
__fastcall TModel3d();
__fastcall TModel3d(char *FileName);
__fastcall ~TModel3d();
TSubModel* __fastcall GetFromName(const char *sName);
//TMaterial* __fastcall GetMaterialFromName(char *sName);
TSubModel* __fastcall AddToNamed(const char *Name, TSubModel *SubModel);
void __fastcall AddTo(TSubModel *tmp,TSubModel *SubModel);
void __fastcall LoadFromTextFile(char *FileName,bool dynamic);
void __fastcall LoadFromBinFile(char *FileName,bool dynamic);
bool __fastcall LoadFromFile(char *FileName,bool dynamic);
void __fastcall SaveToBinFile(char *FileName);
void __fastcall BreakHierarhy();
//renderowanie specjalne
void __fastcall Render(double fSquareDistance,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RenderAlpha(double fSquareDistance,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RaRender(double fSquareDistance,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RaRenderAlpha(double fSquareDistance,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
//jeden kąt obrotu
void __fastcall Render(vector3 pPosition,double fAngle=0,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RenderAlpha(vector3 pPosition,double fAngle=0,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RaRender(vector3 pPosition,double fAngle=0,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RaRenderAlpha(vector3 pPosition,double fAngle=0,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
//trzy kąty obrotu
void __fastcall Render(vector3* vPosition,vector3* vAngle,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RenderAlpha(vector3* vPosition,vector3* vAngle,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RaRender(vector3* vPosition,vector3* vAngle,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
void __fastcall RaRenderAlpha(vector3* vPosition,vector3* vAngle,GLuint *ReplacableSkinId=NULL,int iAlpha=0x30300030);
//inline int __fastcall GetSubModelsCount() { return (SubModelsCount); };
int __fastcall Flags() {return iFlags;};
void __fastcall Init();
char* __fastcall NameGet() {return Root?Root->pName:NULL;};
int __fastcall TerrainCount();
TSubModel* __fastcall TerrainSquare(int n);
void __fastcall TerrainRenderVBO(int n);
};
//---------------------------------------------------------------------------
#endif

590
Mover.cpp Normal file
View File

@@ -0,0 +1,590 @@
//---------------------------------------------------------------------------
#include "Mover.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
// Ra: tu nale¿y przenosiæ funcje z mover.pas, które nie s¹ z niego wywo³ywane.
// Jeœli jakieœ zmienne nie s¹ u¿ywane w mover.pas, te¿ mo¿na je przenosiæ.
// Przeniesienie wszystkiego na raz zrobi³o by zbyt wielki chaos do ogarniêcia.
const dEpsilon=0.01; //1cm (zale¿y od typu sprzêgu...)
__fastcall TMoverParameters::TMoverParameters(double VelInitial,AnsiString TypeNameInit,AnsiString NameInit,
int LoadInitial,AnsiString LoadTypeInitial,int Cab)
: T_MoverParameters(VelInitial,TypeNameInit,NameInit,LoadInitial,LoadTypeInitial,Cab)
{//g³ówny konstruktor
DimHalf.x=0.5*Dim.W; //po³owa szerokoœci, OX jest w bok?
DimHalf.y=0.5*Dim.L; //po³owa d³ugoœci, OY jest do przodu?
DimHalf.z=0.5*Dim.H; //po³owa wysokoœci, OZ jest w górê?
//BrakeLevelSet(-2); //Pascal ustawia na 0, przestawimy na odciêcie (CHK jest jeszcze nie wczytane!)
bPantKurek3=true; //domyœlnie zbiornik pantografu po³¹czony jest ze zbiornikiem g³ównym
iProblem=0; //pojazd w pe³ni gotowy do ruchu
iLights[0]=iLights[1]=0; //œwiat³a zgaszone
};
double __fastcall TMoverParameters::Distance(const TLocation &Loc1,const TLocation &Loc2,const TDimension &Dim1,const TDimension &Dim2)
{//zwraca odleg³oœæ pomiêdzy pojazdami (Loc1) i (Loc2) z uwzglêdnieneim ich d³ugoœci (kule!)
return hypot(Loc2.X-Loc1.X,Loc1.Y-Loc2.Y)-0.5*(Dim2.L+Dim1.L);
};
double __fastcall TMoverParameters::Distance(const vector3 &s1, const vector3 &s2, const vector3 &d1, const vector3 &d2)
{//obliczenie odleg³oœci prostopad³oœcianów o œrodkach (s1) i (s2) i wymiarach (d1) i (d2)
//return 0.0; //bêdzie zg³aszaæ warning - funkcja do usuniêcia, chyba ¿e siê przyda...
};
double __fastcall TMoverParameters::CouplerDist(Byte Coupler)
{//obliczenie odleg³oœci pomiêdzy sprzêgami (kula!)
return Couplers[Coupler].CoupleDist=Distance(Loc,Couplers[Coupler].Connected->Loc,Dim,Couplers[Coupler].Connected->Dim); //odleg³oœæ pomiêdzy sprzêgami (kula!)
};
bool __fastcall TMoverParameters::Attach(Byte ConnectNo,Byte ConnectToNr,TMoverParameters *ConnectTo,Byte CouplingType,bool Forced)
{//³¹czenie do swojego sprzêgu (ConnectNo) pojazdu (ConnectTo) stron¹ (ConnectToNr)
//Ra: zwykle wykonywane dwukrotnie, dla ka¿dego pojazdu oddzielnie
//Ra: trzeba by odró¿niæ wymóg dociœniêcia od uszkodzenia sprzêgu przy podczepianiu AI do sk³adu
if (ConnectTo) //jeœli nie pusty
{
if (ConnectToNr!=2) Couplers[ConnectNo].ConnectedNr=ConnectToNr; //2=nic nie pod³¹czone
TCouplerType ct=ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CouplerType; //typ sprzêgu pod³¹czanego pojazdu
Couplers[ConnectNo].Connected=ConnectTo; //tak podpi¹æ (do siebie) zawsze mo¿na, najwy¿ej bêdzie wirtualny
CouplerDist(ConnectNo); //przeliczenie odleg³oœci pomiêdzy sprzêgami
if (CouplingType==ctrain_virtual) return false; //wirtualny wiêcej nic nie robi
if (Forced?true:((Couplers[ConnectNo].CoupleDist<=dEpsilon)&&(Couplers[ConnectNo].CouplerType!=NoCoupler)&&(Couplers[ConnectNo].CouplerType==ct)))
{//stykaja sie zderzaki i kompatybilne typy sprzegow, chyba ¿e ³¹czenie na starcie
if (Couplers[ConnectNo].CouplingFlag==ctrain_virtual) //jeœli wczeœniej nie by³o po³¹czone
{//ustalenie z której strony rysowaæ sprzêg
Couplers[ConnectNo].Render=true; //tego rysowaæ
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].Render=false; //a tego nie
};
Couplers[ConnectNo].CouplingFlag=CouplingType; //ustawienie typu sprzêgu
//if (CouplingType!=ctrain_virtual) //Ra: wirtualnego nie ³¹czymy zwrotnie!
//{//jeœli ³¹czenie sprzêgiem niewirtualnym, ustawiamy po³¹czenie zwrotne
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag=CouplingType;
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].Connected=this;
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CoupleDist=Couplers[ConnectNo].CoupleDist;
return true;
//}
//pod³¹czenie nie uda³o siê - jest wirtualne
}
}
return false; //brak pod³¹czanego pojazdu, zbyt du¿a odleg³oœæ, niezgodny typ sprzêgu, brak sprzêgu, brak haka
};
bool __fastcall TMoverParameters::Attach(Byte ConnectNo,Byte ConnectToNr,T_MoverParameters *ConnectTo,Byte CouplingType,bool Forced)
{//³¹czenie do (ConnectNo) pojazdu (ConnectTo) stron¹ (ConnectToNr)
return Attach(ConnectNo,ConnectToNr,(TMoverParameters*)ConnectTo,CouplingType,Forced);
};
int __fastcall TMoverParameters::DettachStatus(Byte ConnectNo)
{//Ra: sprawdzenie, czy odleg³oœæ jest dobra do roz³¹czania
//powinny byæ 3 informacje: =0 sprzêg ju¿ roz³¹czony, <0 da siê roz³¹czyæ. >0 nie da siê roz³¹czyæ
if (!Couplers[ConnectNo].Connected)
return 0; //nie ma nic, to roz³¹czanie jest OK
if ((Couplers[ConnectNo].CouplingFlag&ctrain_coupler)==0)
return -Couplers[ConnectNo].CouplingFlag; //hak nie po³¹czony - roz³¹czanie jest OK
if (TestFlag(DamageFlag,dtrain_coupling))
return -Couplers[ConnectNo].CouplingFlag; //hak urwany - roz³¹czanie jest OK
//ABu021104: zakomentowane 'and (CouplerType<>Articulated)' w warunku, nie wiem co to bylo, ale za to teraz dziala odczepianie... :) }
//if (CouplerType==Articulated) return false; //sprzêg nie do rozpiêcia - mo¿e byæ tylko urwany
//Couplers[ConnectNo].CoupleDist=Distance(Loc,Couplers[ConnectNo].Connected->Loc,Dim,Couplers[ConnectNo].Connected->Dim);
CouplerDist(ConnectNo);
if (Couplers[ConnectNo].CouplerType==Screw?Couplers[ConnectNo].CoupleDist<0.0:true)
return -Couplers[ConnectNo].CouplingFlag; //mo¿na roz³¹czaæ, jeœli dociœniêty
return (Couplers[ConnectNo].CoupleDist>0.2)?-Couplers[ConnectNo].CouplingFlag:Couplers[ConnectNo].CouplingFlag;
};
bool __fastcall TMoverParameters::Dettach(Byte ConnectNo)
{//rozlaczanie
if (!Couplers[ConnectNo].Connected) return true; //nie ma nic, to odczepiono
//with Couplers[ConnectNo] do
int i=DettachStatus(ConnectNo); //stan sprzêgu
if (i<0)
{//gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony)
//Couplers[ConnectNo].Connected=NULL; //lepiej zostawic bo przeciez trzeba kontrolowac zderzenia odczepionych
Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag=0; //pozostaje sprzêg wirtualny
Couplers[ConnectNo].CouplingFlag=0; //pozostaje sprzêg wirtualny
return true;
}
else if (i>0)
{//od³¹czamy wê¿e i resztê, pozostaje sprzêg fizyczny, który wymaga dociœniêcia (z wirtualnym nic)
Couplers[ConnectNo].CouplingFlag&=ctrain_coupler;
Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag=Couplers[ConnectNo].CouplingFlag;
}
return false; //jeszcze nie roz³¹czony
};
void __fastcall TMoverParameters::SetCoupleDist()
{//przeliczenie odleg³oœci sprzêgów
if (Couplers[0].Connected)
{
CouplerDist(0);
if (CategoryFlag&2)
{//Ra: dla samochodów zderzanie kul to za ma³o
}
}
if (Couplers[1].Connected)
{
CouplerDist(1);
if (CategoryFlag&2)
{//Ra: dla samochodów zderzanie kul to za ma³o
}
}
};
bool __fastcall TMoverParameters::DirectionForward()
{
if ((MainCtrlPosNo>0)&&(ActiveDir<1)&&(MainCtrlPos==0))
{
++ActiveDir;
DirAbsolute=ActiveDir*CabNo;
if (DirAbsolute)
if (Battery) //jeœli bateria jest ju¿ za³¹czona
BatterySwitch(true); //to w ten oto durny sposób aktywuje siê CA/SHP
SendCtrlToNext("Direction",ActiveDir,CabNo);
return true;
}
else if ((ActiveDir==1)&&(MainCtrlPos==0)&&(TrainType==dt_EZT))
return MinCurrentSwitch(true); //"wysoki rozruch" EN57
return false;
};
// Nastawianie hamulców
void __fastcall TMoverParameters::BrakeLevelSet(double b)
{//ustawienie pozycji hamulca na wartoϾ (b) w zakresie od -2 do BrakeCtrlPosNo
//jedyny dopuszczalny sposób przestawienia hamulca zasadniczego
if (fBrakeCtrlPos==b) return; //nie przeliczaæ, jak nie ma zmiany
fBrakeCtrlPos=b;
BrakeCtrlPosR=b;
if (fBrakeCtrlPos<Handle->GetPos(bh_MIN))
fBrakeCtrlPos=Handle->GetPos(bh_MIN); //odciêcie
else
if (fBrakeCtrlPos>Handle->GetPos(bh_MAX))
fBrakeCtrlPos=Handle->GetPos(bh_MAX);
int x=floor(fBrakeCtrlPos); //jeœli odwo³ujemy siê do BrakeCtrlPos w poœrednich, to musi byæ obciête a nie zaokr¹gone
while ((x>BrakeCtrlPos)&&(BrakeCtrlPos<BrakeCtrlPosNo)) //jeœli zwiêkszy³o siê o 1
if (!T_MoverParameters::IncBrakeLevelOld()) break; //wyjœcie awaryjne
while ((x<BrakeCtrlPos)&&(BrakeCtrlPos>=-1)) //jeœli zmniejszy³o siê o 1
if (!T_MoverParameters::DecBrakeLevelOld()) break;
BrakePressureActual=BrakePressureTable[BrakeCtrlPos+2]; //skopiowanie pozycji
/*
//youBy: obawiam sie, ze tutaj to nie dziala :P
//Ra 2014-03: by³o tak zrobione, ¿e dzia³a³o - po ka¿dej zmianie pozycji by³a wywo³ywana ta funkcja
// if (BrakeSystem==Pneumatic?BrakeSubsystem==Oerlikon:false) //tylko Oerlikon akceptuje u³amki
if(false)
if (fBrakeCtrlPos>0.0)
{//wartoœci poœrednie wyliczamy tylko dla hamowania
double u=fBrakeCtrlPos-double(x); //u³amek ponad wartoœæ ca³kowit¹
if (u>0.0)
{//wyliczamy wartoœci wa¿one
BrakePressureActual.PipePressureVal+=-u*BrakePressureActual.PipePressureVal+u*BrakePressureTable[BrakeCtrlPos+1+2].PipePressureVal;
//BrakePressureActual.BrakePressureVal+=-u*BrakePressureActual.BrakePressureVal+u*BrakePressureTable[BrakeCtrlPos+1].BrakePressureVal; //to chyba nie bêdzie tak dzia³aæ, zw³aszcza w EN57
BrakePressureActual.FlowSpeedVal+=-u*BrakePressureActual.FlowSpeedVal+u*BrakePressureTable[BrakeCtrlPos+1+2].FlowSpeedVal;
}
}
*/
};
bool __fastcall TMoverParameters::BrakeLevelAdd(double b)
{//dodanie wartoœci (b) do pozycji hamulca (w tym ujemnej)
//zwraca false, gdy po dodaniu by³o by poza zakresem
BrakeLevelSet(fBrakeCtrlPos+b);
return b>0.0?(fBrakeCtrlPos<BrakeCtrlPosNo):(BrakeCtrlPos>-1.0); //true, jeœli mo¿na kontynuowaæ
};
bool __fastcall TMoverParameters::IncBrakeLevel()
{//nowa wersja na u¿ytek AI, false gdy osi¹gniêto pozycjê BrakeCtrlPosNo
return BrakeLevelAdd(1.0);
};
bool __fastcall TMoverParameters::DecBrakeLevel()
{//nowa wersja na u¿ytek AI, false gdy osi¹gniêto pozycjê -1
return BrakeLevelAdd(-1.0);
};
bool __fastcall TMoverParameters::ChangeCab(int direction)
{//zmiana kabiny i resetowanie ustawien
if (abs(ActiveCab+direction)<2)
{
// if (ActiveCab+direction=0) then LastCab:=ActiveCab;
ActiveCab=ActiveCab+direction;
if ((BrakeSystem==Pneumatic)&&(BrakeCtrlPosNo>0))
{
// if (BrakeHandle==FV4a) //!!!POBIERAÆ WARTOŒÆ Z KLASY ZAWORU!!!
// BrakeLevelSet(-2); //BrakeCtrlPos=-2;
// else if ((BrakeHandle==FVel6)||(BrakeHandle==St113))
// BrakeLevelSet(2);
// else
// BrakeLevelSet(1);
BrakeLevelSet(Handle->GetPos(bh_NP));
LimPipePress=PipePress;
ActFlowSpeed=0;
}
else
//if (TrainType=dt_EZT) and (BrakeCtrlPosNo>0) then
// BrakeCtrlPos:=5; //z Megapacka
//else
// BrakeLevelSet(0); //BrakeCtrlPos=0;
BrakeLevelSet(Handle->GetPos(bh_NP));
// if not TestFlag(BrakeStatus,b_dmg) then
// BrakeStatus:=b_off; //z Megapacka
MainCtrlPos=0;
ScndCtrlPos=0;
//Ra: to poni¿ej jest bez sensu - mo¿na przejœæ nie wy³¹czaj¹c
//if ((EngineType!=DieselEngine)&&(EngineType!=DieselElectric))
//{
// Mains=false;
// CompressorAllow=false;
// ConverterAllow=false;
//}
//ActiveDir=0;
//DirAbsolute=0;
return true;
}
return false;
};
bool __fastcall TMoverParameters::CurrentSwitch(int direction)
{//rozruch wysoki (true) albo niski (false)
//Ra: przenios³em z Train.cpp, nie wiem czy ma to sens
if (MaxCurrentSwitch(direction))
{if (TrainType!=dt_EZT)
return (MinCurrentSwitch(direction));
}
if (EngineType==DieselEngine) //dla 2Ls150
if (ShuntModeAllow)
if (ActiveDir==0) //przed ustawieniem kierunku
ShuntMode=direction;
return false;
};
void __fastcall TMoverParameters::UpdatePantVolume(double dt)
{//KURS90 - sprê¿arka pantografów; Ra 2014-07: teraz jest to zbiornik rozrz¹du, chocia¿ to jeszcze nie tak
if (EnginePowerSource.SourceType==CurrentCollector) //tylko jeœli pantografuj¹cy
{
//Ra 2014-07: zasadniczo, to istnieje zbiornik rozrz¹du i zbiornik pantografów - na razie mamy razem
//Ra 2014-07: kurek trójdrogowy ³¹czy spr.pom. z pantografami i wy³¹cznikiem ciœnieniowym WS
//Ra 2014-07: zbiornika rozrz¹du nie pompuje siê tu, tylko pantografy; potem mo¿na zamkn¹æ WS i odpaliæ resztê
if ((TrainType==dt_EZT)?(PantPress<ScndPipePress):bPantKurek3) //kurek zamyka po³¹czenie z ZG
{//zbiornik pantografu po³¹czony ze zbiornikiem g³ównym - ma³¹ sprê¿ark¹ siê tego nie napompuje
//Ra 2013-12: Niebugoc³aw mówi, ¿e w EZT nie ma potrzeby odcinaæ kurkiem
PantPress=EnginePowerSource.CollectorParameters.MaxPress; //ograniczenie ciœnienia do MaxPress (tylko w pantografach!)
if (PantPress>ScndPipePress) PantPress=ScndPipePress; //oraz do ScndPipePress
PantVolume=(PantPress+1)*0.1; //objêtoœæ, na wypadek odciêcia kurkiem
}
else
{//zbiornik g³ówny odciêty, mo¿na pompowaæ pantografy
if (PantCompFlag&&Battery) //w³¹czona bateria i ma³a sprê¿arka
PantVolume+=dt*(TrainType==dt_EZT?0.003:0.005)*(2*0.45-((0.1/PantVolume/10)-0.1))/0.45; //nape³nianie zbiornika pantografów
//Ra 2013-12: Niebugoc³aw mówi, ¿e w EZT nabija 1.5 raz wolniej ni¿ jak by³o 0.005
PantPress=(10.0*PantVolume)-1.0; //tu by siê przyda³a objêtoœæ zbiornika
}
if (!PantCompFlag&&(PantVolume>0.1))
PantVolume-=dt*0.0003; //nieszczelnoœci: 0.0003=0.3l/s
if (Mains) //nie wchodziæ w funkcjê bez potrzeby
if (EngineType==ElectricSeriesMotor) //nie dotyczy... czego w³aœciwie?
if (PantPress<EnginePowerSource.CollectorParameters.MinPress)
if ((TrainType&(dt_EZT|dt_ET40|dt_ET41|dt_ET42))?(GetTrainsetVoltage()<EnginePowerSource.CollectorParameters.MinV):true) //to jest trochê proteza; zasilanie cz³onu mo¿e byæ przez sprzêg WN
if (MainSwitch(false))
EventFlag=true; //wywalenie szybkiego z powodu niskiego ciœnienia
if (TrainType!=dt_EZT) //w EN57 pompuje siê tylko w silnikowym
//pierwotnie w CHK pantografy mia³y równie¿ rozrz¹dcze EZT
for (int b=0;b<=1;++b)
if (TestFlag(Couplers[b].CouplingFlag,ctrain_controll))
if (Couplers[b].Connected->PantVolume<PantVolume) //bo inaczej trzeba w obydwu cz³onach przestawiaæ
Couplers[b].Connected->PantVolume=PantVolume; //przekazanie ciœnienia do s¹siedniego cz³onu
//czy np. w ET40, ET41, ET42 pantografy cz³onów maj¹ po³¹czenie pneumatyczne?
//Ra 2014-07: raczej nie - najpierw siê za³¹cza jeden cz³on, a potem mo¿na podnieœæ w drugim
}
else
{//a tu coœ dla SM42 i SM31, aby pokazywaæ na manometrze
PantPress=CntrlPipePress;
}
};
void __fastcall TMoverParameters::UpdateBatteryVoltage(double dt)
{//przeliczenie obci¹¿enia baterii
double sn1,sn2,sn3,sn4,sn5; //Ra: zrobiæ z tego amperomierz NN
if ((BatteryVoltage>0)&&(EngineType!=DieselEngine)&&(EngineType!=WheelsDriven)&&(NominalBatteryVoltage>0))
{
if ((NominalBatteryVoltage/BatteryVoltage<1.22)&&Battery)
{//110V
if (!ConverterFlag)
sn1=(dt*2.0); //szybki spadek do ok 90V
else sn1=0;
if (ConverterFlag)
sn2=-(dt*2.0); //szybki wzrost do 110V
else sn2=0;
if (Mains)
sn3=(dt*0.05);
else sn3=0;
if (iLights[0]&63) //64=blachy, nie ci¹gn¹ pr¹du //rozpisaæ na poszczególne ¿arówki...
sn4=dt*0.003;
else sn4=0;
if (iLights[1]&63) //64=blachy, nie ci¹gn¹ pr¹du
sn5=dt*0.001;
else sn5=0;
};
if ((NominalBatteryVoltage/BatteryVoltage>=1.22)&&Battery)
{//90V
if (PantCompFlag)
sn1=(dt*0.0046);
else sn1=0;
if (ConverterFlag)
sn2=-(dt*50); //szybki wzrost do 110V
else sn2=0;
if (Mains)
sn3=(dt*0.001);
else sn3=0;
if (iLights[0]&63) //64=blachy, nie ci¹gn¹ pr¹du
sn4=(dt*0.0030);
else sn4=0;
if (iLights[1]&63) //64=blachy, nie ci¹gn¹ pr¹du
sn5=(dt*0.0010);
else sn5=0;
};
if (!Battery)
{
if (NominalBatteryVoltage/BatteryVoltage<1.22)
sn1=dt*50;
else
sn1=0;
sn2=dt*0.000001;
sn3=dt*0.000001;
sn4=dt*0.000001;
sn5=dt*0.000001; //bardzo powolny spadek przy wy³¹czonych bateriach
};
BatteryVoltage-=(sn1+sn2+sn3+sn4+sn5);
if (NominalBatteryVoltage/BatteryVoltage>1.57)
if (MainSwitch(false)&&(EngineType!=DieselEngine)&&(EngineType!=WheelsDriven))
EventFlag=true; //wywalanie szybkiego z powodu zbyt niskiego napiecia
if (BatteryVoltage>NominalBatteryVoltage)
BatteryVoltage=NominalBatteryVoltage; //wstrzymanie ³adowania pow. 110V
if (BatteryVoltage<0.01)
BatteryVoltage=0.01;
}
else
if (NominalBatteryVoltage==0)
BatteryVoltage=0;
else
BatteryVoltage=90;
};
/* Ukrotnienie EN57:
1 //uk³ad szeregowy
2 //uk³ad równoleg³y
3 //bocznik 1
4 //bocznik 2
5 //bocznik 3
6 //do przodu
7 //do ty³u
8 //1 przyspieszenie
9 //minus obw. 2 przyspieszenia
10 //jazda na oporach
11 //SHP
12A //podnoszenie pantografu przedniego
12B //podnoszenie pantografu tylnego
13A //opuszczanie pantografu przedniego
13B //opuszczanie wszystkich pantografów
14 //za³¹czenie WS
15 //rozrz¹d (WS, PSR, wa³ ku³akowy)
16 //odblok PN
18 //sygnalizacja przetwornicy g³ównej
19 //luzowanie EP
20 //hamowanie EP
21 //rezerwa** (1900+: zamykanie drzwi prawych)
22 //za³. przetwornicy g³ównej
23 //wy³. przetwornicy g³ównej
24 //za³. przetw. oœwietlenia
25 //wy³. przetwornicy oœwietlenia
26 //sygnalizacja WS
28 //sprê¿arka
29 //ogrzewanie
30 //rezerwa* (1900+: zamykanie drzwi lewych)
31 //otwieranie drzwi prawych
32H //zadzia³anie PN siln. trakcyjnych
33 //sygna³ odjazdu
34 //rezerwa (sygnalizacja poœlizgu)
35 //otwieranie drzwi lewych
ZN //masa
*/
double __fastcall TMoverParameters::ComputeMovement
(double dt,double dt1,
const TTrackShape &Shape,TTrackParam &Track,TTractionParam &ElectricTraction,
const TLocation &NewLoc,TRotation &NewRot
)
{//trzeba po ma³u przenosiæ tu tê funkcjê
double d;
T_MoverParameters::ComputeMovement(dt,dt1,Shape,Track,ElectricTraction,NewLoc,NewRot);
if (Power>1.0) //w rozrz¹dczym nie (jest b³¹d w FIZ!) - Ra 2014-07: teraz we wszystkich
UpdatePantVolume(dt); //Ra 2014-07: obs³uga zbiornika rozrz¹du oraz pantografów
if (EngineType==WheelsDriven)
d=CabNo*dL; //na chwile dla testu
else
d=dL;
DistCounter=DistCounter+fabs(dL)/1000.0;
dL=0;
//koniec procedury, tu nastepuja dodatkowe procedury pomocnicze
//sprawdzanie i ewentualnie wykonywanie->kasowanie poleceñ
if (LoadStatus>0) //czas doliczamy tylko jeœli trwa (roz)³adowanie
LastLoadChangeTime=LastLoadChangeTime+dt; //czas (roz)³adunku
RunInternalCommand();
//automatyczny rozruch
if (EngineType==ElectricSeriesMotor)
if (AutoRelayCheck())
SetFlag(SoundFlag,sound_relay);
/*
else {McZapkie-041003: aby slychac bylo przelaczniki w sterowniczym}
if (EngineType=None) and (MainCtrlPosNo>0) then
for b:=0 to 1 do
with Couplers[b] do
if TestFlag(CouplingFlag,ctrain_controll) then
if Connected^.Power>0.01 then
SoundFlag:=SoundFlag or Connected^.SoundFlag;
*/
if (EngineType==DieselEngine)
if (dizel_Update(dt))
SetFlag(SoundFlag,sound_relay);
//uklady hamulcowe:
if (VeselVolume>0)
Compressor=CompressedVolume/VeselVolume;
else
{
Compressor=0;
CompressorFlag=false;
};
ConverterCheck();
if (CompressorSpeed>0.0) //sprê¿arka musi mieæ jak¹œ niezerow¹ wydajnoœæ
CompressorCheck(dt); //¿eby rozwa¿aæ jej za³¹czenie i pracê
UpdateBrakePressure(dt);
UpdatePipePressure(dt);
UpdateBatteryVoltage(dt);
UpdateScndPipePressure(dt); // druga rurka, youBy
//hamulec antypoœlizgowy - wy³¹czanie
if ((BrakeSlippingTimer>0.8)&&(ASBType!=128)) //ASBSpeed=0.8
Hamulec->ASB(0);
//SetFlag(BrakeStatus,-b_antislip);
BrakeSlippingTimer=BrakeSlippingTimer+dt;
//sypanie piasku - wy³¹czone i piasek siê nie koñczy - b³êdy AI
//if AIControllFlag then
// if SandDose then
// if Sand>0 then
// begin
// Sand:=Sand-NPoweredAxles*SandSpeed*dt;
// if Random<dt then SandDose:=false;
// end
// else
// begin
// SandDose:=false;
// Sand:=0;
// end;
//czuwak/SHP
//if (Vel>10) and (not DebugmodeFlag) then
if (!DebugModeFlag)
SecuritySystemCheck(dt1);
return d;
};
double __fastcall TMoverParameters::FastComputeMovement
(double dt,
const TTrackShape &Shape,TTrackParam &Track,
const TLocation &NewLoc,TRotation &NewRot
)
{//trzeba po ma³u przenosiæ tu tê funkcjê
double d;
T_MoverParameters::FastComputeMovement(dt,Shape,Track,NewLoc,NewRot);
if (Power>1.0) //w rozrz¹dczym nie (jest b³¹d w FIZ!)
UpdatePantVolume(dt); //Ra 2014-07: obs³uga zbiornika rozrz¹du oraz pantografów
if (EngineType==WheelsDriven)
d=CabNo*dL; //na chwile dla testu
else
d=dL;
DistCounter=DistCounter+fabs(dL)/1000.0;
dL=0;
//koniec procedury, tu nastepuja dodatkowe procedury pomocnicze
//sprawdzanie i ewentualnie wykonywanie->kasowanie poleceñ
if (LoadStatus>0) //czas doliczamy tylko jeœli trwa (roz)³adowanie
LastLoadChangeTime=LastLoadChangeTime+dt; //czas (roz)³adunku
RunInternalCommand();
if (EngineType==DieselEngine)
if (dizel_Update(dt))
SetFlag(SoundFlag,sound_relay);
//uklady hamulcowe:
if (VeselVolume>0)
Compressor=CompressedVolume/VeselVolume;
else
{
Compressor=0;
CompressorFlag=false;
};
ConverterCheck();
if (CompressorSpeed>0.0) //sprê¿arka musi mieæ jak¹œ niezerow¹ wydajnoœæ
CompressorCheck(dt); //¿eby rozwa¿aæ jej za³¹czenie i pracê
UpdateBrakePressure(dt);
UpdatePipePressure(dt);
UpdateScndPipePressure(dt); // druga rurka, youBy
UpdateBatteryVoltage(dt);
//hamulec antyposlizgowy - wy³¹czanie
if ((BrakeSlippingTimer>0.8)&&(ASBType!=128)) //ASBSpeed=0.8
Hamulec->ASB(0);
BrakeSlippingTimer=BrakeSlippingTimer+dt;
return d;
};
double __fastcall TMoverParameters::ShowEngineRotation(int VehN)
{//pokazywanie obrotów silnika, równie¿ dwóch dalszych pojazdów (3×SN61)
int b;
switch (VehN)
{//numer obrotomierza
case 1:
return fabs(enrot);
case 2:
for (b=0;b<=1;++b)
if (TestFlag(Couplers[b].CouplingFlag,ctrain_controll))
if (Couplers[b].Connected->Power>0.01)
return fabs(Couplers[b].Connected->enrot);
break;
case 3: //to nie uwzglêdnia ewentualnego odwrócenia pojazdu w œrodku
for (b=0;b<=1;++b)
if (TestFlag(Couplers[b].CouplingFlag,ctrain_controll))
if (Couplers[b].Connected->Power>0.01)
if (TestFlag(Couplers[b].Connected->Couplers[b].CouplingFlag,ctrain_controll))
if (Couplers[b].Connected->Couplers[b].Connected->Power>0.01)
return fabs(Couplers[b].Connected->Couplers[b].Connected->enrot);
break;
};
return 0.0;
};
void __fastcall TMoverParameters::ConverterCheck()
{//sprawdzanie przetwornicy
if (ConverterAllow&&Mains)
ConverterFlag=true;
else
ConverterFlag=false;
};
int __fastcall TMoverParameters::ShowCurrent(Byte AmpN)
{//odczyt ampera¿u
switch (EngineType)
{case ElectricInductionMotor:
switch (AmpN)
{//do asynchronicznych
case 1: return WindingRes*Mm/Vadd;
case 2: return dizel_fill*WindingRes;
default: return T_MoverParameters::ShowCurrent(AmpN);
}
break;
case DieselElectric:
return fabs(Im);
break;
default:
return T_MoverParameters::ShowCurrent(AmpN);
}
};

173
Mover.h Normal file
View File

@@ -0,0 +1,173 @@
//---------------------------------------------------------------------------
#ifndef MoverH
#define MoverH
//---------------------------------------------------------------------------
#include "Mover.hpp"
// Ra: Niestety "_mover.hpp" siê nieprawid³owo generuje - przek³ada sobie TCoupling na sam koniec.
// Przy wszelkich poprawkach w "_mover.pas" trzeba skopiowaæ rêcznie "_mover.hpp" do "mover.hpp" i
// poprawiæ b³êdy! Tak a¿ do wydzielnia TCoupling z Pascala do C++...
// Docelowo obs³ugê sprzêgów (³¹czenie, roz³¹czanie, obliczanie odleg³oœci, przesy³ komend)
// trzeba przenieϾ na poziom DynObj.cpp.
// Obs³ugê silniników te¿ trzeba wydzieliæ do osobnego modu³u, bo ka¿dy osobno mo¿e mieæ poœlizg.
#include "dumb3d.h"
using namespace Math3D;
enum TProblem //lista problemów taboru, które uniemo¿liwiaj¹ jazdê
{//flagi bitowe
pr_Hamuje=1, //pojazd ma za³¹czony hamulec lub zatarte osie
pr_Pantografy=2, //pojazd wymaga napompowania pantografów
pr_Ostatni=0x80000000 //ostatnia flaga bitowa
};
class TMoverParameters : public T_MoverParameters
{//Ra: wrapper na kod pascalowy, przejmuj¹cy jego funkcje
public:
vector3 vCoulpler[2]; //powtórzenie wspó³rzêdnych sprzêgów z DynObj :/
vector3 DimHalf; //po³owy rozmiarów do obliczeñ geometrycznych
//int WarningSignal; //0: nie trabi, 1,2: trabi syren¹ o podanym numerze
unsigned char WarningSignal; //tymczasowo 8bit, ze wzglêdu na funkcje w MTools
double fBrakeCtrlPos; //p³ynna nastawa hamulca zespolonego
bool bPantKurek3; //kurek trójdrogowy (pantografu): true=po³¹czenie z ZG, false=po³¹czenie z ma³¹ sprê¿ark¹
int iProblem; //flagi problemów z taborem, aby AI nie musia³o porównywaæ; 0=mo¿e jechaæ
int iLights[2]; //bity zapalonych œwiate³ tutaj, ¿eby da³o siê liczyæ pobór pr¹du
private:
double __fastcall CouplerDist(Byte Coupler);
public:
__fastcall TMoverParameters(double VelInitial,AnsiString TypeNameInit,AnsiString NameInit,
int LoadInitial,AnsiString LoadTypeInitial,int Cab);
//obs³uga sprzêgów
double __fastcall Distance(const TLocation &Loc1,const TLocation &Loc2,const TDimension &Dim1,const TDimension &Dim2);
double __fastcall Distance(const vector3 &Loc1,const vector3 &Loc2,const vector3 &Dim1,const vector3 &Dim2);
bool __fastcall Attach(Byte ConnectNo,Byte ConnectToNr,TMoverParameters *ConnectTo,Byte CouplingType,bool Forced=false);
bool __fastcall Attach(Byte ConnectNo,Byte ConnectToNr,T_MoverParameters *ConnectTo,Byte CouplingType,bool Forced=false);
int __fastcall DettachStatus(Byte ConnectNo);
bool __fastcall Dettach(Byte ConnectNo);
void __fastcall SetCoupleDist();
bool __fastcall DirectionForward();
void __fastcall BrakeLevelSet(double b);
bool __fastcall BrakeLevelAdd(double b);
bool __fastcall IncBrakeLevel(); //wersja na u¿ytek AI
bool __fastcall DecBrakeLevel();
bool __fastcall ChangeCab(int direction);
bool __fastcall CurrentSwitch(int direction);
void __fastcall UpdateBatteryVoltage(double dt);
double __fastcall ComputeMovement
(double dt,double dt1,
const TTrackShape &Shape,TTrackParam &Track,TTractionParam &ElectricTraction,
const TLocation &NewLoc,TRotation &NewRot
);
double __fastcall FastComputeMovement
(double dt,
const TTrackShape &Shape,TTrackParam &Track,
const TLocation &NewLoc,TRotation &NewRot
);
double __fastcall ShowEngineRotation(int VehN);
//double __fastcall GetTrainsetVoltage(void);
//bool __fastcall Physic_ReActivation(void);
//double __fastcall LocalBrakeRatio(void);
//double __fastcall ManualBrakeRatio(void);
//double __fastcall PipeRatio(void);
//double __fastcall RealPipeRatio(void);
//double __fastcall BrakeVP(void);
//bool __fastcall DynamicBrakeSwitch(bool Switch);
//bool __fastcall SendCtrlBroadcast(AnsiString CtrlCommand, double ctrlvalue);
//bool __fastcall SendCtrlToNext(AnsiString CtrlCommand, double ctrlvalue, double dir);
//bool __fastcall CabActivisation(void);
//bool __fastcall CabDeactivisation(void);
//bool __fastcall IncMainCtrl(int CtrlSpeed);
//bool __fastcall DecMainCtrl(int CtrlSpeed);
//bool __fastcall IncScndCtrl(int CtrlSpeed);
//bool __fastcall DecScndCtrl(int CtrlSpeed);
//bool __fastcall AddPulseForce(int Multipler);
//bool __fastcall SandDoseOn(void);
//bool __fastcall SecuritySystemReset(void);
//void __fastcall SecuritySystemCheck(double dt);
//bool __fastcall BatterySwitch(bool State);
//bool __fastcall EpFuseSwitch(bool State);
//bool __fastcall IncBrakeLevelOld(void);
//bool __fastcall DecBrakeLevelOld(void);
//bool __fastcall IncLocalBrakeLevel(Byte CtrlSpeed);
//bool __fastcall DecLocalBrakeLevel(Byte CtrlSpeed);
//bool __fastcall IncLocalBrakeLevelFAST(void);
//bool __fastcall DecLocalBrakeLevelFAST(void);
//bool __fastcall IncManualBrakeLevel(Byte CtrlSpeed);
//bool __fastcall DecManualBrakeLevel(Byte CtrlSpeed);
//bool __fastcall EmergencyBrakeSwitch(bool Switch);
//bool __fastcall AntiSlippingBrake(void);
//bool __fastcall BrakeReleaser(Byte state);
//bool __fastcall SwitchEPBrake(Byte state);
//bool __fastcall AntiSlippingButton(void);
//bool __fastcall IncBrakePress(double &brake, double PressLimit, double dp);
//bool __fastcall DecBrakePress(double &brake, double PressLimit, double dp);
//bool __fastcall BrakeDelaySwitch(Byte BDS);
//bool __fastcall IncBrakeMult(void);
//bool __fastcall DecBrakeMult(void);
//void __fastcall UpdateBrakePressure(double dt);
//void __fastcall UpdatePipePressure(double dt);
//void __fastcall CompressorCheck(double dt);
void __fastcall UpdatePantVolume(double dt);
//void __fastcall UpdateScndPipePressure(double dt);
//void __fastcall UpdateBatteryVoltage(double dt);
//double __fastcall GetDVc(double dt);
//void __fastcall ComputeConstans(void);
//double __fastcall ComputeMass(void);
//double __fastcall Adhesive(double staticfriction);
//double __fastcall TractionForce(double dt);
//double __fastcall FrictionForce(double R, Byte TDamage);
//double __fastcall BrakeForce(const TTrackParam &Track);
//double __fastcall CouplerForce(Byte CouplerN, double dt);
//void __fastcall CollisionDetect(Byte CouplerN, double dt);
//double __fastcall ComputeRotatingWheel(double WForce, double dt, double n);
//bool __fastcall SetInternalCommand(AnsiString NewCommand, double NewValue1, double NewValue2);
//double __fastcall GetExternalCommand(AnsiString &Command);
//bool __fastcall RunCommand(AnsiString command, double CValue1, double CValue2);
//bool __fastcall RunInternalCommand(void);
//void __fastcall PutCommand(AnsiString NewCommand, double NewValue1, double NewValue2, const TLocation
// &NewLocation);
//bool __fastcall DirectionBackward(void);
//bool __fastcall MainSwitch(bool State);
//bool __fastcall ConverterSwitch(bool State);
//bool __fastcall CompressorSwitch(bool State);
void __fastcall ConverterCheck();
//bool __fastcall FuseOn(void);
//bool __fastcall FuseFlagCheck(void);
//void __fastcall FuseOff(void);
int __fastcall ShowCurrent(Byte AmpN);
//double __fastcall v2n(void);
//double __fastcall current(double n, double U);
//double __fastcall Momentum(double I);
//double __fastcall MomentumF(double I, double Iw, Byte SCP);
//bool __fastcall CutOffEngine(void);
//bool __fastcall MaxCurrentSwitch(bool State);
//bool __fastcall ResistorsFlagCheck(void);
//bool __fastcall MinCurrentSwitch(bool State);
//bool __fastcall AutoRelaySwitch(bool State);
//bool __fastcall AutoRelayCheck(void);
//bool __fastcall dizel_EngageSwitch(double state);
//bool __fastcall dizel_EngageChange(double dt);
//bool __fastcall dizel_AutoGearCheck(void);
//double __fastcall dizel_fillcheck(Byte mcp);
//double __fastcall dizel_Momentum(double dizel_fill, double n, double dt);
//bool __fastcall dizel_Update(double dt);
//bool __fastcall LoadingDone(double LSpeed, AnsiString LoadInit);
//void __fastcall ComputeTotalForce(double dt, double dt1, bool FullVer);
//double __fastcall ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track
// , TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot);
//double __fastcall FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const
// TLocation &NewLoc, TRotation &NewRot);
//bool __fastcall ChangeOffsetH(double DeltaOffset);
//__fastcall T_MoverParameters(double VelInitial, AnsiString TypeNameInit, AnsiString NameInit, int LoadInitial
// , AnsiString LoadTypeInitial, int Cab);
//bool __fastcall LoadChkFile(AnsiString chkpath);
//bool __fastcall CheckLocomotiveParameters(bool ReadyFlag, int Dir);
//AnsiString __fastcall EngineDescription(int what);
//bool __fastcall DoorLeft(bool State);
//bool __fastcall DoorRight(bool State);
//bool __fastcall DoorBlockedFlag(void);
//bool __fastcall PantFront(bool State);
//bool __fastcall PantRear(bool State);
//
};
#endif

167
Names.cpp Normal file
View File

@@ -0,0 +1,167 @@
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Names.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
/*
Moduł zarządzający plikami oraz wyszukiwaniem obiektów wg nazw.
1. Ma przydzielony z góry (EU07.INI) obszar pamięci (rzędu 16MB).
2. W przypadku przepełnienia dostępnej pamięci wystąpi błąd wczytywania.
3. Obszar ten będzie zużywany na rekordy obiektów oraz ciągi tekstowe z nazwami.
4. Rekordy będą sortowane w ramach typu (tekstury, dźwięki, modele, node, eventy).
5. Pierwszy etap wyszukiwania to 5 bitów z pierwszego bajtu i 3 z drugiego (256).
6. Dla plików istnieje możliwość wczytania ich w innym terminie.
7. Możliwość wczytania plików w oddzielnym watku (np. tekstur).
Obsługiwane pliki:
1. Tekstury, można wczytywać później, rekord przechowuje numer podany przez kartę graficzną.
2. Dźwięki, można wczytać później.
3. Modele, można wczytać później o ile nie mają animacji eventami i nie dotyczą pojazdów.
Obiekty sortowane wg nazw, można dodawać i usuwać komórki scenerii:
4. Tory, drogi, rzeki - wyszukiwanie w celu sprawdzenia zajetości.
5. Eventy - wyszukiwane przy zewnętrznym wywołaniu oraz podczas wczytywania.
6. Pojazdy - wyszukiwane w celu wysyłania komend.
7. Egzemplarze modeli animowanych - wyszukiwanie w celu połączenia z animacjami.
*/
void __fastcall ItemRecord::TreeAdd(ItemRecord *r,int c)
{//dodanie rekordu do drzewa - ustalenie w której gałęzi
//zapisać w (iFlags) ile znaków jest zgodnych z nadrzędnym, żeby nie sprawdzać wszystkich od zera
if ((cName[c]&&r->cName[c])?cName[c]==r->cName[c]:false)
TreeAdd(r,c+1); //ustawić wg kolejnego znaku, chyba że zero
else
if ((unsigned char)(cName[c])<(unsigned char)(r->cName[c]))
{//zero jest najmniejsze - doczepiamy jako (rNext)
if (!rNext) rNext=r;
else rNext->TreeAdd(r,0); //doczepić do tej gałęzi
}
else
{
if (!rPrev) rPrev=r;
else rPrev->TreeAdd(r,0); //doczepić do tej gałęzi
}
};
void __fastcall ItemRecord::ListGet(ItemRecord *r,int*&n)
{//rekurencyjne wypełnianie posortowanej listy na podstawie drzewa
if (rPrev) rPrev->ListGet(r,n); //dodanie wszystkich wcześniejszych
*n++=this-r; //dodanie swojego indeksu do tabeli
if (rNext) rNext->ListGet(r,n); //dodanie wszystkich późniejszych
};
void* __fastcall ItemRecord::TreeFind(const char *n)
{//wyszukanie ciągu (n)
ItemRecord *r=TreeFindRecord(n);
return r?r->pData:NULL;
};
ItemRecord* __fastcall ItemRecord::TreeFindRecord(const char *n)
{//wyszukanie ciągu (n)
ItemRecord *r=this; //żeby nie robić rekurencji
int i=0;
do
{
if (!n[i]) if (!r->cName[i]) return r; //znaleziony
if (n[i]==r->cName[i])
++i; //porównać kolejny znak
else
if ((unsigned char)(n[i])<(unsigned char)(r->cName[i]))
{
i=0; //porównywać od nowa
r=r->rPrev; //wcześniejsza gałąź drzewa
}
else
{
i=0; //porównywać od nowa
r=r->rNext; //późniejsza gałąź drzewa
}
} while (r);
return NULL;
};
__fastcall TNames::TNames()
{//tworzenie bufora
iSize=16*1024*1024; //rozmiar bufora w bajtach
cBuffer=new char[iSize];
ZeroMemory(cBuffer,iSize); //nie trzymać jakiś starych śmieci
rRecords=(ItemRecord*)cBuffer;
cLast=cBuffer+iSize; //bajt za buforem
iLast=-1;
ZeroMemory(rTypes,20*sizeof(ItemRecord*));
};
int __fastcall TNames::Add(int t,const char *n)
{//dodanie obiektu typu (t) o nazwie (n)
int len=strlen(n)+1; //ze znacznikiem końca
cLast-=len; //rezerwacja miejsca
memcpy(cLast,n,len); //przekopiowanie tekstu do bufora
//cLast[len-1]='\0';
rRecords[++iLast].cName=cLast; //połączenie nazwy z rekordem
rRecords[iLast].iFlags=t;
if (!rTypes[t])
rTypes[t]=rRecords+iLast; //korzeń drzewa, bo nie było wcześniej
else
rTypes[t]->TreeAdd(rRecords+iLast,0); //doczepienie jako gałąź
//rTypes[t]=Sort(t); //sortowanie uruchamiać ręcznie
if ((iLast&0x3F)==0) //nie za często, bo sortowania zajmą więcej czasu niż wyszukiwania
Sort(t); //optymalizacja drzewa co jakiś czas
return iLast;
}
int __fastcall TNames::Add(int t,const char *n,void *d)
{
int i=Add(t,n);
rRecords[iLast].pData=d;
return i;
};
bool __fastcall TNames::Update(int t,const char *n,void *d)
{//dodanie jeśli nie ma, wymiana (d), gdy jest
ItemRecord *r=FindRecord(t,n); //najpierw sprawdzić, czy już jest
if (r)
{//przy zdublowaniu nazwy podmieniać w drzewku na późniejszy
r->pData=d;
return true; //duplikat
}
//Add(t,n,d); //nazwa unikalna
return false; //został dodany nowy
};
ItemRecord* __fastcall TNames::TreeSet(int *n,int d,int u)
{//rekurencyjne wypełnianie drzewa pozycjami od (d) do (u)
if (d==u)
{
rRecords[n[d]].rPrev=rRecords[n[d]].rNext=NULL;
return rRecords+n[d]; //tej gałęzi nie ma
}
else if (d>u) return NULL;
int p=(u+d)>>1; //połowa
rRecords[n[p]].rPrev=TreeSet(n,d,p-1); //zapisanie wcześniejszych gałęzi
rRecords[n[p]].rNext=TreeSet(n,p+1,u); //zapisanie późniejszych gałęzi
return rRecords+n[p];
};
void __fastcall TNames::Sort(int t)
{//przebudowa drzewa typu (t), zwraca wierzchołek drzewa
if (iLast<3) return; //jak jest mało, to nie ma sensu sortować
if (rTypes[t]) //jeśli jest jakiś rekord danego typu
{int *r=new int[iLast+1]; //robocza tablica indeksów - numery posortowanych rekordów
int *q=r; //wskaźnik roboczy, przekazywany przez referencję
rTypes[t]->ListGet(rRecords,q); //drzewo jest już posortowane - zamienić je na listę
rTypes[t]=TreeSet(r,0,(q-r)-1);
delete[] r;
}
return;
};
ItemRecord* __fastcall TNames::FindRecord(const int t,const char *n)
{//poszukiwanie rekordu w celu np. zmiany wskaźnika
return rTypes[t]?rTypes[t]->TreeFindRecord(n):NULL;
};

53
Names.h Normal file
View File

@@ -0,0 +1,53 @@
//---------------------------------------------------------------------------
#ifndef NamesH
#define NamesH
//---------------------------------------------------------------------------
class ItemRecord
{//rekord opisuj¹cy obiekt; raz utworzony nie przemieszcza siê
//rozmiar rekordu mo¿na zmieniæ w razie potrzeby
public:
char *cName; //wskaŸnik do nazwy umieszczonej w buforze
int iFlags; //flagi bitowe
ItemRecord *rPrev,*rNext; //posortowane drzewo (przebudowywane w razie potrzeby)
union
{void *pData; //wskaŸnik do obiektu
int iData; //albo numer obiektu (tekstury)
unsigned int uData;
};
//typedef
void __fastcall ListGet(ItemRecord *r,int*&n);
void __fastcall TreeAdd(ItemRecord *r,int c);
template <typename TOut> inline TOut* DataGet() {return (TOut*)pData;};
template <typename TOut> inline void DataSet(TOut *x) {pData=(void*)x;};
void* __fastcall TreeFind(const char *n);
ItemRecord* __fastcall TreeFindRecord(const char *n);
};
class TNames
{
public:
int iSize; //rozmiar bufora
char *cBuffer; //bufor dla rekordów (na pocz¹tku) i nazw (na koñcu)
ItemRecord *rRecords; //rekordy na pocz¹tku bufora
char *cLast; //ostatni u¿yty bajt na nazwy
ItemRecord *rTypes[20]; //ro¿ne typy obiektów (pocz¹tek drzewa)
int iLast; //ostatnio u¿yty rekord
public:
__fastcall TNames();
int __fastcall Add(int t,const char *n); //dodanie obiektu typu (t)
int __fastcall Add(int t,const char *n,void *d); //dodanie obiektu z wskaŸnikiem
int __fastcall Add(int t,const char *n,int d); //dodanie obiektu z numerem
bool __fastcall Update(int t,const char *n,void *d); //dodanie jeœli nie ma, wymiana (d), gdy jest
void __fastcall TreeSet();
ItemRecord* __fastcall TreeSet(int *n,int d,int u);
void __fastcall Sort(int t); //przebudowa drzewa typu (t)
ItemRecord* __fastcall Item(int n); //rekord o numerze (n)
inline void* Find(const int t,const char *n)
{return rTypes[t]?rTypes[t]->TreeFind(n):NULL;};
ItemRecord* __fastcall FindRecord(const int t,const char *n);
//template <typename TOut> inline TOut* Find(const int t,const char *n)
//{return (TOut*)(rTypes[t]->TreeFind(n));};
};
#endif

151
QueryParserComp.hpp Normal file
View File

@@ -0,0 +1,151 @@
// Borland C++ Builder
// Copyright (c) 1995, 1999 by Borland International
// All rights reserved
// (DO NOT EDIT: machine generated header) 'QueryParserComp.pas' rev: 5.00
#ifndef QueryParserCompHPP
#define QueryParserCompHPP
#pragma delphiheader begin
#pragma option push -w-
#pragma option push -Vx
#include <SysUtils.hpp> // Pascal unit
#include <Classes.hpp> // Pascal unit
#include <SysInit.hpp> // Pascal unit
#include <System.hpp> // Pascal unit
//-- user supplied -----------------------------------------------------------
namespace Queryparsercomp
{
//-- type declarations -------------------------------------------------------
#pragma option push -b-
enum TTokenType { ttString, ttSymbol, ttComment, ttDelimiter, ttSpecialChar, ttStatementDelimiter, ttCommentedSymbol,
ttCommentDelimiter };
#pragma option pop
typedef Set<char, 0, 255> TSetOfChar;
typedef AnsiString TComment[2];
#pragma option push -b-
enum TCharacterType { ctSymbol, ctBeginComment, ctEndComment, ctDelimiter, ctString, ctSpecialChar }
;
#pragma option pop
#pragma option push -b-
enum QueryParserComp__1 { cmt1, cmt2, cmt3 };
#pragma option pop
typedef Set<QueryParserComp__1, cmt1, cmt3> TCommentType;
typedef AnsiString QueryParserComp__2[3][2];
typedef void __fastcall (__closure *TEndOfStatement)(System::TObject* Sender, AnsiString SQLStatement
);
class DELPHICLASS TQueryParserComp;
class PASCALIMPLEMENTATION TQueryParserComp : public Classes::TComponent
{
typedef Classes::TComponent inherited;
private:
Classes::TStringStream* FStream;
bool FEOF;
AnsiString FToken;
TTokenType FTokenType;
bool FComment;
bool FString;
bool FWasString;
TCommentType FCommentType;
AnsiString FStringDelimiters;
AnsiString FLastStringDelimiterFound;
int FSymbolsCount;
AnsiString FSpecialCharacters;
bool FRemoveStrDelimiter;
AnsiString FStringToParse;
int FGoPosition;
TEndOfStatement FOnStatementDelimiter;
bool FCountFromStatement;
Classes::TStringList* FStatementDelimiters;
char FStringDelimiter;
bool FGenerateOnStmtDelimiter;
void __fastcall Init(void);
void __fastcall SetStringToParse(AnsiString AStringToParse);
bool __fastcall StatementDelimiter(void);
bool __fastcall CheckForBeginComment(void);
bool __fastcall CheckForEndComment(char Character);
TCharacterType __fastcall CharacterType(char Character);
bool __fastcall CheckCharcterType(char Character);
bool __fastcall StringDelimiter(char Character);
bool __fastcall SpecialCharacter(char Character);
void __fastcall RemoveStringDelimiter(AnsiString &Source);
void __fastcall SetDelimiterType(AnsiString Source);
void __fastcall SetToken(void);
void __fastcall SetSD(Classes::TStringList* ASD);
void __fastcall SetSpecialCharacters(AnsiString ASpecialCharacters);
void __fastcall SetStringDelimiters(AnsiString AStringDelimiters);
protected:
DYNAMIC void __fastcall DoStatementDelimiter(void);
public:
__fastcall virtual TQueryParserComp(Classes::TComponent* AOwner);
__fastcall virtual ~TQueryParserComp(void);
void __fastcall LoadStringToParse(AnsiString FileName);
void __fastcall First(void);
void __fastcall FirstToken(void);
void __fastcall NextToken(void);
AnsiString __fastcall GetNextSymbol();
__property bool EndOfFile = {read=FEOF, nodefault};
__property bool Comment = {read=FComment, nodefault};
__property AnsiString Token = {read=FToken};
__property TTokenType TokenType = {read=FTokenType, nodefault};
__property char CurrentStringDelimiter = {read=FStringDelimiter, nodefault};
__property int SymbolsCount = {read=FSymbolsCount, default=0};
__property Classes::TStringStream* StringStream = {read=FStream};
__published:
__property bool IsEOFStmtDelimiter = {read=FGenerateOnStmtDelimiter, write=FGenerateOnStmtDelimiter
, nodefault};
__property AnsiString StringDelimiters = {read=FStringDelimiters, write=SetStringDelimiters};
__property AnsiString SpecialCharacters = {read=FSpecialCharacters, write=SetSpecialCharacters};
__property bool RemoveStrDelimiter = {read=FRemoveStrDelimiter, write=FRemoveStrDelimiter, nodefault
};
__property bool CountFromStatement = {read=FCountFromStatement, write=FCountFromStatement, nodefault
};
__property AnsiString TextToParse = {read=FStringToParse, write=SetStringToParse};
__property Classes::TStringList* StatementDelimiters = {read=FStatementDelimiters, write=SetSD};
__property TEndOfStatement OnStatementDelimiter = {read=FOnStatementDelimiter, write=FOnStatementDelimiter
};
};
//-- var, const, procedure ---------------------------------------------------
extern PACKAGE System::ResourceString _sTextNotSet;
#define Queryparsercomp_sTextNotSet System::LoadResourceString(&Queryparsercomp::_sTextNotSet)
extern PACKAGE System::ResourceString _sIllegalSpecialChar;
#define Queryparsercomp_sIllegalSpecialChar System::LoadResourceString(&Queryparsercomp::_sIllegalSpecialChar)
extern PACKAGE System::ResourceString _sIllegalStringChar;
#define Queryparsercomp_sIllegalStringChar System::LoadResourceString(&Queryparsercomp::_sIllegalStringChar)
static const char CR = '\xd';
static const char LF = '\xa';
static const char TAB = '\x9';
#define CRLF "\r\n"
extern PACKAGE TSetOfChar Delimiters;
extern PACKAGE AnsiString Comments[3][2];
extern PACKAGE void __fastcall Register(void);
} /* namespace Queryparsercomp */
#if !defined(NO_IMPLICIT_NAMESPACE_USE)
using namespace Queryparsercomp;
#endif
#pragma option pop // -w-
#pragma option pop // -Vx
#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif // QueryParserComp

724
QueryParserComp.pas Normal file
View File

@@ -0,0 +1,724 @@
unit QueryParserComp;
interface
uses
Classes, Sysutils;
resourcestring
sTextNotSet = 'You must set the TextToParse property first.';
sIllegalSpecialChar = 'Illegal special character.';
sIllegalStringChar = 'Illegal string delimiter.';
type
TTokenType = (ttString, ttSymbol, ttComment, ttDelimiter, ttSpecialChar,
ttStatementDelimiter, ttCommentedSymbol, ttCommentDelimiter);
TSetOfChar = set of Char;
TComment = array[0..1] of string;
TCharacterType = (ctSymbol, ctBeginComment, ctEndComment, ctDelimiter,
ctString, ctSpecialChar);
TCommentType = set of (cmt1, cmt2, cmt3);
const
CR = #13;
LF = #10;
TAB = #9;
CRLF = CR + LF;
Delimiters: TSetOfChar = [' ', ',', ';', CR, LF, TAB];
Comments: array[0..2] of TComment = (('/*', '*/'), ('#', LF), ('//', LF));
type
TEndOfStatement = procedure(Sender: TObject; SQLStatement: String) of object;
TQueryParserComp = class(TComponent)
private
FStream: TStringStream;
FEOF: Boolean;
FToken: String;
FTokenType: TTokenType;
FComment: Boolean;
FString: Boolean;
FWasString: Boolean;
FCommentType: TCommentType;
FStringDelimiters: String;
FLastStringDelimiterFound: String;
FSymbolsCount: Integer;
FSpecialCharacters: String;
FRemoveStrDelimiter: Boolean;
FStringToParse: String;
FGoPosition: Integer;
FOnStatementDelimiter: TEndOfStatement;
FCountFromStatement: Boolean;
FStatementDelimiters: TStringList;
FStringDelimiter: Char;
FGenerateOnStmtDelimiter: Boolean;
procedure Init;
procedure SetStringToParse(AStringToParse: String);
function StatementDelimiter: Boolean;
function CheckForBeginComment: Boolean;
function CheckForEndComment(Character: Char): Boolean;
function CharacterType(Character: Char): TCharacterType;
function CheckCharcterType(Character: Char): Boolean;
function StringDelimiter(Character: Char): Boolean;
function SpecialCharacter(Character: Char): Boolean;
procedure RemoveStringDelimiter(var Source: String);
procedure SetDelimiterType(Source: String);
procedure SetToken;
procedure SetSD(ASD: TStringList);
procedure SetSpecialCharacters(ASpecialCharacters: String);
procedure SetStringDelimiters(AStringDelimiters: String);
protected
procedure DoStatementDelimiter; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure LoadStringToParse(FileName: string);
procedure First;
procedure FirstToken;
procedure NextToken;
function GetNextSymbol : string;
property EndOfFile: Boolean read FEOF;
property Comment: Boolean read FComment;
property Token: String read FToken;
property TokenType: TTokenType read FTokenType;
property CurrentStringDelimiter: Char read FStringDelimiter;
property SymbolsCount: Integer read FSymbolsCount default 0;
property StringStream: TStringStream read FStream;
published
property IsEOFStmtDelimiter: Boolean read FGenerateOnStmtDelimiter
write FGenerateOnStmtDelimiter;
property StringDelimiters: String read FStringDelimiters
write SetStringDelimiters;
property SpecialCharacters: String read FSpecialCharacters
write SetSpecialCharacters;
property RemoveStrDelimiter: Boolean read FRemoveStrDelimiter
write FRemoveStrDelimiter;
property CountFromStatement: Boolean read FCountFromStatement
write FCountFromStatement;
property TextToParse: String read FStringToParse
write SetStringToParse;
property StatementDelimiters: TStringList read FStatementDelimiters write SetSD;
property OnStatementDelimiter: TEndOfStatement read FOnStatementDelimiter
write FOnStatementDelimiter;
end;
procedure Register;
implementation
{ TSQLParser }
procedure Register;
begin
RegisterComponents('Samples', [TQueryParserComp]);
end;
constructor TQueryParserComp.Create(AOwner: TComponent);
begin
inherited;
FStatementDelimiters := TStringList.Create;
FStatementDelimiters.Add('GO');
FStatementDelimiters.Add(';');
FCountFromStatement := True;
end;
procedure TQueryParserComp.LoadStringToParse(FileName: string);
var
fs:TFileStream;
size:integer;
begin
fs:= TFileStream.Create(FileName, fmOpenRead);
size:= fs.Size;
if Assigned(FStream) then
FStream.Free;
FStream := TStringStream.Create('');
FStream.CopyFrom(fs,size);
fs.Free;
Init;
First;
end;
procedure TQueryParserComp.FirstToken;
begin
Init;
NextToken;
end;
function TQueryParserComp.CheckForBeginComment: Boolean;
var
Buffer: String;
begin
Result := False;
if not FEOF and not FString then
begin
Buffer := FStream.ReadString(1);
if cmt1 in FCommentType then
if Buffer[1] = '*' then
begin
FCommentType := [cmt1];
Result := True;
end;
if cmt2 in FCommentType then
if Buffer[1] = '/' then
begin
FCommentType := [cmt2];
Result := True;
end;
if cmt3 in FCommentType then
if Buffer[1] = '-' then
begin
FCommentType := [cmt3];
Result := True;
end;
FStream.Seek(-1, soFromCurrent);
end;
end;
procedure TQueryParserComp.SetDelimiterType(Source: String);
begin
FToken := Source[1];
if ((cmt2 in FCommentType) or (cmt3 in FCommentType)) and FComment
and ((Source[1] = CR) or (Source[1] = LF)) then
begin
FComment := False;
FTokenType := ttCommentDelimiter;
end
else
FTokenType := ttDelimiter;
end;
procedure TQueryParserComp.NextToken;
var
Buffer: String;
ETextNotSet: Exception;
begin
if FEOF then
Exit;
if not Assigned(FStream) then
begin
ETextNotSet := Exception.Create(sTextNotSet);
raise ETextNotSet;
end;
if not FString then
FStringDelimiter := ' ';
FToken := '';
if not FEOF then
begin
Buffer := FStream.ReadString(1);
if Length(Buffer) > 0 then
begin
if (Buffer[1] in Delimiters) and not (FString or FComment)then
SetDelimiterType(Buffer)
else
begin
if FStream.Position > 0 then
FStream.Seek(-1, soFromCurrent);
SetToken;
end;
end
else
FEOF := True;
end;
case FTokenType of
ttSymbol: Inc(FSymbolsCount);
ttString:
begin
FStringDelimiter := FToken[1];
if FRemoveStrDelimiter then
RemoveStringDelimiter(FToken);
end;
end;
if StatementDelimiter then
FTokenType := ttStatementDelimiter;
if FEOF then
begin
FLastStringDelimiterFound := '';
FWasString := False;
FString := False;
if FGenerateOnStmtDelimiter then
DoStatementDelimiter;
end;
end;
function TQueryParserComp.GetNextSymbol : string;
begin
GetNextSymbol:= '';
while ( not EndOfFile) do
begin
NextToken;
if (TokenType=ttSymbol) then
begin
GetNextSymbol:= Token;
break;
end
end
end;
function TQueryParserComp.StatementDelimiter: Boolean;
var
i: Integer;
begin
Result := False;
if not FString then
for i := 0 to FStatementDelimiters.Count - 1 do
begin
Result := (UpperCase(FToken) = UpperCase(FStatementDelimiters.Strings[i]));
if Result then
begin
if FCountFromStatement then
FSymbolsCount := 0;
DoStatementDelimiter;
Break;
end;
end;
end;
function TQueryParserComp.CharacterType(Character: Char): TCharacterType;
begin
Result := ctSymbol;
case Character of
'/':
begin
if not FComment then
begin
FCommentType := [cmt1, cmt2];
if CheckForBeginComment then
Result := ctBeginComment;
end;
end;
'-':
begin
if not FComment then
begin
FCommentType := [cmt3];
if CheckForBeginComment then
Result := ctBeginComment;
end;
end;
'*':
begin
if CheckForEndComment(Character) then
Result := ctEndComment;
end;
CR, LF, ' ', ',', TAB:
begin
if CheckForEndComment(Character) then
Result := ctEndComment
else
Result := ctDelimiter;
if FString and ((Character = CR) or (Character = LF)) then
begin
FString := False;
FWasString := False;
Result := ctDelimiter;
end;
end;
end;
if not FString then
if SpecialCharacter(Character) then
begin
if not FComment then
Result := ctSpecialChar;
end;
if not FComment then
if StringDelimiter(Character) then
begin
Result := ctSymbol;
if FString then
begin
FLastStringDelimiterFound := '';
FWasString := True;
FString := False;
end
else
begin
FWasString := False;
FString := True;
end;
end;
end;
function TQueryParserComp.CheckForEndComment(Character: Char): Boolean;
var
Buffer: String;
begin
Result := False;
if not FComment or FString then
Exit;
if not FEOF then
begin
if cmt1 in FCommentType then
begin
Buffer := FStream.ReadString(1);
if Buffer[1] = '/' then
Result := True;
FStream.Seek(-1, soFromCurrent);
end;
if (cmt2 in FCommentType) or (cmt3 in FCommentType) then
begin
if (Character = CR) or (Character = LF) then
Result := True;
end;
end;
end;
function TQueryParserComp.CheckCharcterType(Character: Char): Boolean;
var
Buffer: String;
begin
Result := False;
case CharacterType(Character) of
ctBeginComment:
begin
if not FComment then
begin
if FToken <> '' then
begin
FStream.Seek(-1, soFromCurrent);
FTokenType := ttSymbol;
end
else
begin
FComment := True;
FToken := FToken + Character;
Buffer := FStream.ReadString(1);
FToken := FToken + Buffer;
FTokenType := ttComment;
end;
Result := True;
end;
end;
ctEndComment:
begin
if FComment then
begin
Result := True;
if FToken <> '' then
begin
FStream.Seek(-1, soFromCurrent);
FTokenType := ttCommentedSymbol;
end
else
begin
FComment := False;
FToken := FToken + Character;
if FCommentType = [cmt1] then
begin
Buffer := FStream.ReadString(1);
FToken := FToken + Buffer;
end;
FTokenType := ttComment;
end;
end;
end;
ctSymbol:
begin
FToken := FToken + Character;
if FComment then
FTokenType := ttCommentedSymbol
else
begin
if FString or FWasString then
begin
if FWasString then
begin
FTokenType := ttString;
FWasString := False;
Result := True;
end
else
FTokenType := ttString;
end
else
FTokenType := ttSymbol;
end;
end;
ctSpecialChar:
begin
if FToken <> '' then
begin
FStream.Seek(-1, soFromCurrent);
FTokenType := ttSymbol;
end
else
begin
FToken := FToken + Character;
FTokenType := ttSpecialChar;
end;
Result := True;
end;
ctDelimiter:
begin
FTokenType := ttDelimiter;
Result := True;
end;
end
end;
procedure TQueryParserComp.RemoveStringDelimiter(var Source: String);
var
EndOfString: Integer;
i: Integer;
begin
for i := 1 to Length(FStringDelimiters) do
begin
EndOfString := 1;
while not (EndOfString = 0) do
begin
EndOfString := Pos(FStringDelimiters[i], Source);
if EndOfString <> 0 then
begin
FLastStringDelimiterFound := Copy(FStringDelimiters, i, 1);
Delete(Source, EndOfString, 1);
end;
end;
end;
end;
function TQueryParserComp.StringDelimiter(Character: Char): Boolean;
var
i: Integer;
Buffer: String;
begin
Result := False;
for i := 1 to Length(FStringDelimiters) do
if (Character = FStringDelimiters[i]) then
begin
if (FLastStringDelimiterFound = '') then
FLastStringDelimiterFound := FStringDelimiters[i];
if (FLastStringDelimiterFound = FStringDelimiters[i]) then
begin
if not FEOF then
Buffer := FStream.ReadString(1);
if Length(Buffer) > 0 then
begin
if Buffer[1] <> Character then
begin
FStream.Seek(-1, soFromCurrent);
Result := True;
end
else
FToken := FToken + Buffer;
end
else
Result := True;
end;
end;
end;
function TQueryParserComp.SpecialCharacter(Character: Char): Boolean;
var
i: Integer;
begin
Result := False;
for i := 1 to Length(FSpecialCharacters) do
if Character = FSpecialCharacters[i] then
Result := True;
end;
procedure TQueryParserComp.SetToken;
var
EndToken: Boolean;
Buffer: String;
begin
EndToken := False;
while not (EndToken or FEOF) do
begin
FEOF := FStream.Position >= FStream.Size-1;
Buffer := FStream.ReadString(1);
if not (Buffer[1] in Delimiters) then
EndToken := CheckCharcterType(Buffer[1])
else
begin
if not (FString or FComment) then
begin
EndToken := True;
FStream.Seek(-1, soFromCurrent);
end
else
begin
if FString and ((Buffer[1] = CR) or (Buffer[1] = LF)) then
begin
FString := False;
FWasString := False;
EndToken := True;
end
else
if FComment and ((cmt2 in FCommentType) or
(cmt3 in FCommentType)) and ((Buffer[1] = CR) or
(Buffer[1] = LF)) then
begin
EndToken := True;
FStream.Seek(-1, soFromCurrent);
FComment := False;
FCommentType := [];
end
else
FToken := FToken + Buffer;
end;
end;
end; //while
end;
destructor TQueryParserComp.Destroy;
begin
if Assigned(FStream) then
FStream.Free;
inherited Destroy;
end;
procedure TQueryParserComp.DoStatementDelimiter;
var
Buffer: String;
CurrentPosition: Integer;
begin
if Assigned(FOnStatementDelimiter) then
begin
CurrentPosition := FStream.Position;
FStream.Seek(FGoPosition, soFromBeginning);
Buffer := FStream.ReadString(CurrentPosition-FGoPosition-Length(FToken));
FStream.Seek(Length(FToken), soFromCurrent);
if FStream.Position >= FStream.Size then
FEOF := True;
FGoPosition := FStream.Position;
if FCountFromStatement then
FSymbolsCount := 0;
FOnStatementDelimiter(Self, Trim(Buffer));
end;
end;
procedure TQueryParserComp.SetStringToParse(AStringToParse: String);
begin
if AStringToParse = '' then
Exit;
if Assigned(FStream) then
FStream.Free;
TrimRight(AStringToParse);
FStream := TStringStream.Create(AStringToParse);
FStringToParse := AStringToParse;
Init;
end;
procedure TQueryParserComp.SetSD(ASD: TStringList);
begin
FStatementDelimiters.Assign(ASD);
end;
procedure TQueryParserComp.First;
begin
Init;
end;
procedure TQueryParserComp.Init;
var
ETextNotSet: Exception;
begin
if not Assigned(FStream) then
begin
ETextNotSet := Exception.Create(sTextNotSet);
raise ETextNotSet;
end;
FStream.Seek(0, soFromBeginning);
FToken := '';
FTokenType := ttString;
FComment := False;
FCommentType := [];
FEOF := False;
FSymbolsCount := 0;
FGoPosition := 0;
FLastStringDelimiterFound := '';
FWasString := False;
FString := False;
end;
procedure TQueryParserComp.SetSpecialCharacters(ASpecialCharacters: String);
var
i: Integer;
k: Integer;
IllegalSpecialChar: Exception;
begin
for i := 1 to Length(ASpecialCharacters) do
begin
for k := 0 to FStatementDelimiters.Count - 1 do
begin
if (Pos(ASpecialCharacters[i], FStatementDelimiters.Strings[k]) <> 0) then
begin
IllegalSpecialChar := Exception.Create(sIllegalSpecialChar);
raise IllegalSpecialChar;
end;
end;
if (ASpecialCharacters[i] in Delimiters) or
(Pos(ASpecialCharacters[i], FStringDelimiters) <> 0) then
begin
IllegalSpecialChar := Exception.Create(sIllegalSpecialChar);
raise IllegalSpecialChar;
end;
end;
FSpecialCharacters := ASpecialCharacters;
end;
procedure TQueryParserComp.SetStringDelimiters(AStringDelimiters: String);
var
i: Integer;
k: Integer;
IllegalStringChar: Exception;
begin
for i := 1 to Length(AStringDelimiters) do
begin
for k := 0 to FStatementDelimiters.Count - 1 do
begin
if (Pos(AStringDelimiters[i], FStatementDelimiters.Strings[k]) <> 0) then
begin
IllegalStringChar := Exception.Create(sIllegalStringChar);
raise IllegalStringChar;
end;
end;
if (AStringDelimiters[i] in Delimiters) or
(Pos(AStringDelimiters[i], FSpecialCharacters) <> 0) then
begin
IllegalStringChar := Exception.Create(sIllegalStringChar);
raise IllegalStringChar;
end;
end;
FStringDelimiters := AStringDelimiters;
end;
end.

277
RealSound.cpp Normal file
View File

@@ -0,0 +1,277 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "math.h"
#include "RealSound.h"
#include "Globals.h"
#include "Timer.h"
#include "Logs.h"
#include "McZapkie\mctools.hpp"
__fastcall TRealSound::TRealSound()
{
pSound=NULL;
dSoundAtt=-1;
AM=0.0;
AA=0.0;
FM=0.0;
FA=0.0;
vSoundPosition.x=0;
vSoundPosition.y=0;
vSoundPosition.z=0;
fDistance=fPreviousDistance=0.0;
fFrequency=22050.0; //częstotliwość samplowania pliku
iDoppler=0; //normlanie jest załączony; !=0 - modyfikacje
bLoopPlay=false; //dźwięk wyłączony
}
__fastcall TRealSound::~TRealSound()
{
//if (this) if (pSound) pSound->Stop();
}
void __fastcall TRealSound::Free()
{
}
void __fastcall TRealSound::Init(char *SoundName, double DistanceAttenuation, double X, double Y, double Z,bool Dynamic,bool freqmod,double rmin)
{
//Nazwa=SoundName; //to tak raczej nie zadziała, (SoundName) jest tymczasowe
pSound=TSoundsManager::GetFromName(SoundName,Dynamic,&fFrequency);
if (pSound)
{
if (freqmod)
if (fFrequency!=22050.0)
{//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: "+AnsiString(SoundName)+", as modulated, should have 22.05kHz in header");
}
AM=1.0;
pSound->SetVolume(DSBVOLUME_MIN);
}
else
{//nie ma dźwięku, to jest wysyp
AM=0;
ErrorLog("Missed sound: "+AnsiString(SoundName));
}
if (DistanceAttenuation>0.0)
{
dSoundAtt=DistanceAttenuation*DistanceAttenuation;
vSoundPosition.x=X;
vSoundPosition.y=Y;
vSoundPosition.z=Z;
if (rmin<0) iDoppler=1; //wyłączenie efektu Dopplera, np. dla dźwięku ptaków
}
else
dSoundAtt=-1;
};
double __fastcall TRealSound::ListenerDistance(vector3 ListenerPosition)
{
if (dSoundAtt==-1)
{ return 0.0; }
else
{ return SquareMagnitude(ListenerPosition-vSoundPosition); }
}
void __fastcall TRealSound::Play(double Volume, int Looping, bool ListenerInside, vector3 NewPosition)
{
if (!pSound) return;
long int vol;
double dS;
// double Distance;
DWORD stat;
if ((Global::bSoundEnabled)&&(AM!=0))
{
if (Volume>1.0)
Volume=1.0;
fPreviousDistance=fDistance;
fDistance=0.0; //??
if (dSoundAtt>0.0)
{
vSoundPosition=NewPosition;
dS=dSoundAtt; //*dSoundAtt; //bo odleglosc podawana w kwadracie
fDistance=ListenerDistance(Global::pCameraPosition);
if (ListenerInside) //osłabianie dźwięków z odległością
Volume=Volume*dS/(dS+fDistance);
else
Volume=Volume*dS/(dS+2*fDistance); //podwójne dla ListenerInside=false
}
if (iDoppler) //
{//Ra 2014-07: efekt Dopplera nie zawsze jest wskazany
//if (FreeFlyModeFlag) //gdy swobodne latanie - nie sprawdza się to
fPreviousDistance=fDistance; //to efektu Dopplera nie będzie
}
if (Looping) //dźwięk zapętlony można wyłączyć i zostanie włączony w miarę potrzeby
bLoopPlay=true; //dźwięk wyłączony
//McZapkie-010302 - babranie tylko z niezbyt odleglymi dźwiękami
if ((dSoundAtt==-1)||(fDistance<20.0*dS))
{
// vol=2*Volume+1;
// if (vol<1) vol=1;
// vol=10000*(log(vol)-1);
// vol=10000*(vol-1);
//int glos=1;
//Volume=Volume*glos; //Ra: whatta hella is this
if (Volume<0.0) Volume=0.0;
vol=-5000.0+5000.0*Volume;
if (vol>=0)
vol=-1;
if (Timer::GetSoundTimer()||!Looping) //Ra: po co to jest?
pSound->SetVolume(vol); //Attenuation, in hundredths of a decibel (dB).
pSound->GetStatus(&stat);
if (!(stat&DSBSTATUS_PLAYING))
pSound->Play(0,0,Looping);
}
else //wylacz dzwiek bo daleko
{//Ra 2014-09: oddalanie się nie może być powodem do wyłączenie dźwięku
/*
// Ra: stara wersja, ale podobno lepsza
pSound->GetStatus(&stat);
if (bLoopPlay) //jeśli zapętlony, to zostanie ponownie włączony, o ile znajdzie się bliżej
if (stat&DSBSTATUS_PLAYING)
pSound->Stop();
// Ra: wyłączyłem, bo podobno jest gorzej niż wcześniej
//ZiomalCl: dźwięk po wyłączeniu sam się nie włączy, gdy wrócimy w rejon odtwarzania
pSound->SetVolume(DSBVOLUME_MIN); //dlatego lepiej go wyciszyć na czas oddalenia się
pSound->GetStatus(&stat);
if (!(stat&DSBSTATUS_PLAYING))
pSound->Play(0,0,Looping); //ZiomalCl: włączenie odtwarzania rownież i tu, gdyż jesli uruchamiamy dźwięk poza promieniem, nie uruchomi się on w ogóle
*/
}
}
};
void __fastcall TRealSound::Start()
{//włączenie dźwięku
};
void __fastcall TRealSound::Stop()
{
DWORD stat;
if (pSound)
if ((Global::bSoundEnabled)&&(AM!=0))
{
bLoopPlay=false; //dźwięk wyłączony
pSound->GetStatus(&stat);
if (stat&DSBSTATUS_PLAYING)
pSound->Stop();
}
};
void __fastcall TRealSound::AdjFreq(double Freq, double dt) //McZapkie TODO: dorobic tu efekt Dopplera
//Freq moze byc liczba dodatnia mniejsza od 1 lub wieksza od 1
{
float df, Vlist, Vsrc;
if ((Global::bSoundEnabled) && (AM!=0))
{
if (dt>0)
//efekt Dopplera
{
Vlist=(sqrt(fPreviousDistance)-sqrt(fDistance))/dt;
df= Freq*(1+Vlist/299.8);
}
else
df=Freq;
if (Timer::GetSoundTimer())
{
df=fFrequency*df; //TODO - brac czestotliwosc probkowania z wav
pSound->SetFrequency(( df<DSBFREQUENCY_MIN ? DSBFREQUENCY_MIN : (df>DSBFREQUENCY_MAX ? DSBFREQUENCY_MAX : df) ) );
}
}
}
double TRealSound::GetWaveTime() //McZapkie: na razie tylko dla 22KHz/8bps
{//używana do pomiaru czasu dla dźwięków z początkiem i końcem
if (!pSound) return 0.0;
double WaveTime;
DSBCAPS caps;
caps.dwSize=sizeof(caps);
pSound->GetCaps(&caps);
WaveTime=caps.dwBufferBytes;
return WaveTime/fFrequency; //(pSound->); // wielkosc w bajtach przez czestotliwosc probkowania
}
void __fastcall TRealSound::SetPan(int Pan)
{
pSound->SetPan(Pan);
}
int TRealSound::GetStatus()
{
DWORD stat;
if ((Global::bSoundEnabled) && (AM!=0))
{
pSound->GetStatus(&stat);
return stat;
}
else
return 0;
}
void __fastcall TRealSound::ResetPosition()
{
if (pSound) //Ra: znowu jakiś badziew!
pSound->SetCurrentPosition(0);
}
void __fastcall TTextSound::Init(char *SoundName,double SoundAttenuation,double X,double Y,double Z,bool Dynamic,bool freqmod,double rmin)
{//dodatkowo doczytuje plik tekstowy
TRealSound::Init(SoundName,SoundAttenuation,X,Y,Z,Dynamic,freqmod,rmin);
fTime=GetWaveTime();
AnsiString txt=AnsiString(SoundName);
txt.Delete(txt.Length()-3,4); //obcięcie rozszerzenia
for (int i=txt.Length();i>0;--i)
if (txt[i]=='/') txt[i]='\\'; //bo nie rozumi
txt+="-"+Global::asLang+".txt"; //już może być w różnych językach
if (!FileExists(txt))
txt="sounds\\"+txt; //ścieżka może nie być podana
if (FileExists(txt))
{//wczytanie
TFileStream *ts=new TFileStream(txt,fmOpenRead);
asText=AnsiString::StringOfChar(' ',ts->Size);
ts->Read(asText.c_str(),ts->Size);
delete ts;
}
};
void __fastcall TTextSound::Play(double Volume,int Looping,bool ListenerInside,vector3 NewPosition)
{
if (!asText.IsEmpty())
{//jeśli ma powiązany tekst
DWORD stat;
pSound->GetStatus(&stat);
if (!(stat&DSBSTATUS_PLAYING)) //jeśli nie jest aktualnie odgrywany
{
int i;
AnsiString t=asText;
do
{//na razie zrobione jakkolwiek, docelowo przenieść teksty do tablicy nazw
i=t.Pos("\r"); //znak nowej linii
if (!i)
Global::tranTexts.Add(t.c_str(),fTime,true);
else
{
Global::tranTexts.Add(t.SubString(1,i-1).c_str(),fTime,true);
t.Delete(1,i);
while (t.IsEmpty()?false:(unsigned char)(t[1])<33)
t.Delete(1,1);
}
} while (i>0);
}
}
TRealSound::Play(Volume,Looping,ListenerInside,NewPosition);
};
//---------------------------------------------------------------------------
#pragma package(smart_init)

66
RealSound.h Normal file
View File

@@ -0,0 +1,66 @@
//---------------------------------------------------------------------------
#ifndef RealSoundH
#define RealSoundH
#include "Sound.h"
#include "Geometry.h"
class TRealSound
{
protected:
PSound pSound;
char* Nazwa; //dla celow odwszawiania
double fDistance,fPreviousDistance; //dla liczenia Dopplera
float fFrequency; //częstotliwość samplowania pliku
int iDoppler; //Ra 2014-07: możliwość wyłączenia efektu Dopplera np. dla śpiewu ptaków
public:
vector3 vSoundPosition; //polozenie zrodla dzwieku
double dSoundAtt; //odleglosc polowicznego zaniku dzwieku
double AM; //mnoznik amplitudy
double AA; //offset amplitudy
double FM; //mnoznik czestotliwosci
double FA; //offset czestotliwosci
bool bLoopPlay; //czy zapętlony dźwięk jest odtwarzany
__fastcall TRealSound();
__fastcall ~TRealSound();
void __fastcall Free();
void __fastcall Init(char *SoundName,double SoundAttenuation,double X,double Y,double Z,bool Dynamic,bool freqmod=false,double rmin=0.0);
double __fastcall ListenerDistance(vector3 ListenerPosition);
void __fastcall Play(double Volume,int Looping,bool ListenerInside,vector3 NewPosition);
void __fastcall Start();
void __fastcall Stop();
void __fastcall AdjFreq(double Freq,double dt);
void __fastcall SetPan(int Pan);
double GetWaveTime(); //McZapkie TODO: dorobic dla roznych bps
int GetStatus();
void __fastcall ResetPosition();
//void __fastcall FreqReset(float f=22050.0) {fFrequency=f;};
};
class TTextSound : public TRealSound
{//dźwięk ze stenogramem
AnsiString asText;
float fTime; //czas trwania
public:
void __fastcall Init(char *SoundName,double SoundAttenuation,double X,double Y,double Z,bool Dynamic,bool freqmod=false,double rmin=0.0);
void __fastcall Play(double Volume,int Looping,bool ListenerInside,vector3 NewPosition);
};
class TSynthSound
{//klasa generująca sygnał odjazdu (Rp12, Rp13), potem rozbudować o pracę manewrowego...
int iIndex[44]; //indeksy początkowe, gdy mamy kilka wariantów dźwięków składowych
//0..9 - cyfry 0..9
//10..19 - liczby 10..19
//21..29 - dziesiątki (*21==*10?)
//31..39 - setki 100,200,...,800,900
//40 - "tysiąc"
//41 - "tysiące"
//42 - indeksy początkowe dla "odjazd"
//43 - indeksy początkowe dla "gotów"
PSound *sSound; //posortowana tablica dźwięków, rozmiar zależny od liczby znalezionych plików
//a może zamiast wielu plików/dźwięków zrobić jeden połączony plik i posługiwać się czasem od..do?
};
//---------------------------------------------------------------------------
#endif

78
ResourceManager.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "ResourceManager.h"
#include "Logs.h"
#include <sstream>
ResourceManager::Resources ResourceManager::_resources;
double ResourceManager::_expiry = 5.0f;
double ResourceManager::_lastUpdate = 0.0f;
double ResourceManager::_lastReport = 0.0f;
void ResourceManager::Register(Resource* resource)
{
_resources.push_back(resource);
};
void ResourceManager::Unregister(Resource* resource)
{
Resources::iterator iter = std::find(_resources.begin(), _resources.end(), resource);
if(iter != _resources.end())
_resources.erase(iter);
resource->Release();
};
class ResourceExpired
{
public:
ResourceExpired(double time): _time(time) { };
bool operator()(Resource* resource)
{
return (resource->GetLastUsage() < _time);
}
private:
double _time;
};
void ResourceManager::Sweep(double currentTime)
{
if(currentTime - _lastUpdate < _expiry)
return;
Resources::iterator begin = std::remove_if(_resources.begin(), _resources.end(), ResourceExpired(currentTime - _expiry));
#ifdef RESOURCE_REPORTING
if(begin != _resources.end())
WriteLog("Releasing resources");
#endif
for(Resources::iterator iter = begin; iter != _resources.end(); iter++)
(*iter)->Release();
#ifdef RESOURCE_REPORTING
if(begin != _resources.end())
{
std::ostringstream msg;
msg << "Released " << (_resources.end() - begin) << " resources";
WriteLog(msg.str().c_str());
};
#endif
_resources.erase(begin, _resources.end());
#ifdef RESOURCE_REPORTING
if(currentTime - _lastReport > 30.0f)
{
std::ostringstream msg;
msg << "Resources count: " << _resources.size();
WriteLog(msg.str().c_str());
_lastReport = currentTime;
};
#endif
_lastUpdate = currentTime;
};

45
ResourceManager.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef RESOURCEMANAGER_H
#define RESOURCEMANAGER_H 1
#include <vector>
#include <algorithm>
#pragma hdrstop
class Resource
{
public:
virtual void Release() = 0;
double GetLastUsage() const { return _lastUsage; }
protected:
void SetLastUsage(double lastUsage) { _lastUsage = lastUsage; }
private:
double _lastUsage;
};
class ResourceManager
{
public:
static void Register(Resource* resource);
static void Unregister(Resource* resource);
static void Sweep(double currentTime);
static void SetExpiry(double expiry) { _expiry = expiry; }
private:
typedef std::vector<Resource*> Resources;
static double _expiry;
static double _lastUpdate;
static double _lastReport;
static Resources _resources;
};
#endif

918
Segment.cpp Normal file
View File

@@ -0,0 +1,918 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#pragma hdrstop
#include "opengl/glew.h"
//#include "opengl/glut.h"
#include "Segment.h"
#include "Usefull.h"
#include "Globals.h"
#include "Track.h"
//#define Precision 10000
#pragma package(smart_init)
//---------------------------------------------------------------------------
//101206 Ra: trapezoidalne drogi
//110806 Ra: odwrócone mapowanie wzdłuż - Point1 == 1.0
AnsiString __fastcall Where(vector3 p)
{//zamiana współrzędnych na tekst, używana w błędach
return AnsiString(p.x)+" "+AnsiString(p.y)+" "+AnsiString(p.z);
};
__fastcall TSegment::TSegment(TTrack *owner)
{
Point1=CPointOut=CPointIn=Point2=vector3(0.0f,0.0f,0.0f);
fLength=0;
fRoll1=0;
fRoll2=0;
fTsBuffer=NULL;
fStep=0;
pOwner=owner;
};
__fastcall TSegment::~TSegment()
{
SafeDeleteArray(fTsBuffer);
};
bool __fastcall TSegment::Init(
vector3 NewPoint1,vector3 NewPoint2,double fNewStep,
double fNewRoll1,double fNewRoll2)
{//wersja dla prostego - wyliczanie punktów kontrolnych
vector3 dir;
if (fNewRoll1==fNewRoll2)
{//faktyczny prosty
dir=Normalize(NewPoint2-NewPoint1); //wektor kierunku o długości 1
return TSegment::Init(
NewPoint1,dir,-dir,NewPoint2,
fNewStep,fNewRoll1,fNewRoll2,
false);
}
else
{//prosty ze zmienną przechyłką musi być segmentowany jak krzywe
dir=(NewPoint2-NewPoint1)/3.0; //punkty kontrolne prostego są w 1/3 długości
return TSegment::Init(
NewPoint1,NewPoint1+dir,NewPoint2-dir,NewPoint2,
fNewStep,fNewRoll1,fNewRoll2,
true);
}
};
bool __fastcall TSegment::Init(
vector3 &NewPoint1,vector3 NewCPointOut,vector3 NewCPointIn,vector3 &NewPoint2,
double fNewStep,double fNewRoll1, double fNewRoll2, bool bIsCurve)
{//wersja uniwersalna (dla krzywej i prostego)
Point1=NewPoint1;
CPointOut=NewCPointOut;
CPointIn=NewCPointIn;
Point2=NewPoint2;
//poprawienie przechyłki
fRoll1=DegToRad(fNewRoll1); //Ra: przeliczone jest bardziej przydatne do obliczeń
fRoll2=DegToRad(fNewRoll2);
if (Global::bRollFix)
{//Ra: poprawianie przechyłki
// Przechyłka powinna być na środku wewnętrznej szyny, a standardowo jest w osi
// toru. Dlatego trzeba podnieść tor oraz odpowiednio podwyższyć podsypkę.
// Nie wykonywać tej funkcji, jeśli podwyższenie zostało uwzględnione w edytorze.
// Problematyczne mogą byc rozjazdy na przechyłce - lepiej je modelować w edytorze.
// Na razie wszystkie scenerie powinny być poprawiane.
// Jedynie problem będzie z podwójną rampą przechyłkową, która w środku będzie
// mieć moment wypoziomowania, ale musi on być również podniesiony.
if (fRoll1!=0.0)
{//tylko jeśli jest przechyłka
double w1=fabs(sin(fRoll1)*0.75); //0.5*w2+0.0325; //0.75m dla 1.435
Point1.y+=w1; //modyfikacja musi być przed policzeniem dalszych parametrów
if (bCurve) CPointOut.y+=w1; //prosty ma wektory jednostkowe
pOwner->MovedUp1(w1);//zwrócić trzeba informację o podwyższeniu podsypki
}
if (fRoll2!=0.0)
{
double w2=fabs(sin(fRoll2)*0.75); //0.5*w2+0.0325; //0.75m dla 1.435
Point2.y+=w2; //modyfikacja musi być przed policzeniem dalszych parametrów
if (bCurve) CPointIn.y+=w2; //prosty ma wektory jednostkowe
//zwrócić trzeba informację o podwyższeniu podsypki
}
}
//Ra: ten kąt jeszcze do przemyślenia jest
fDirection=-atan2(Point2.x-Point1.x,Point2.z-Point1.z); //kąt w planie, żeby nie liczyć wielokrotnie
bCurve=bIsCurve;
if (bCurve)
{//przeliczenie współczynników wielomianu, będzie mniej mnożeń i można policzyć pochodne
vC=3.0*(CPointOut-Point1); //t^1
vB=3.0*(CPointIn-CPointOut)-vC; //t^2
vA=Point2-Point1-vC-vB; //t^3
fLength=ComputeLength();
}
else
fLength=(Point1-Point2).Length();
fStep=fNewStep;
if (fLength<=0)
{
ErrorLog("Bad geometry: Length <= 0 in TSegment::Init at "+Where(Point1));
//MessageBox(0,"Length<=0","TSegment::Init",MB_OK);
return false; //zerowe nie mogą być
}
fStoop=atan2((Point2.y-Point1.y),fLength); //pochylenie toru prostego, żeby nie liczyć wielokrotnie
SafeDeleteArray(fTsBuffer);
if ((bCurve) && (fStep>0))
{//Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
double s=0;
int i=0;
iSegCount=ceil(fLength/fStep); //potrzebne do VBO
//fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
fTsBuffer=new double[iSegCount+1];
fTsBuffer[0]=0; /* TODO : fix fTsBuffer */
while (s<fLength)
{
i++;
s+=fStep;
if (s>fLength) s=fLength;
fTsBuffer[i]=GetTFromS(s);
}
}
if (fLength>500)
{//tor ma pojemność 40 pojazdów, więc nie może być za długi
ErrorLog("Bad geometry: Length > 500m at "+Where(Point1));
//MessageBox(0,"Length>500","TSegment::Init",MB_OK);
return false;
}
return true;
}
vector3 __fastcall TSegment::GetFirstDerivative(double fTime)
{
double fOmTime = 1.0 - fTime;
double fPowTime = fTime;
vector3 kResult = fOmTime*(CPointOut-Point1);
//int iDegreeM1 = 3 - 1;
double fCoeff = 2*fPowTime;
kResult = (kResult+fCoeff*(CPointIn-CPointOut))*fOmTime;
fPowTime *= fTime;
kResult += fPowTime*(Point2-CPointIn);
kResult *= 3;
return kResult;
}
double __fastcall TSegment::RombergIntegral(double fA, double fB)
{
double fH = fB - fA;
const int ms_iOrder= 5;
double ms_apfRom[2][ms_iOrder];
ms_apfRom[0][0] = 0.5*fH*((GetFirstDerivative(fA).Length())+(GetFirstDerivative(fB).Length()));
for (int i0 = 2, iP0 = 1; i0 <= ms_iOrder; i0++, iP0 *= 2, fH *= 0.5)
{
// approximations via the trapezoid rule
double fSum = 0.0;
int i1;
for (i1 = 1; i1 <= iP0; i1++)
fSum += (GetFirstDerivative(fA + fH*(i1-0.5)).Length());
// Richardson extrapolation
ms_apfRom[1][0] = 0.5*(ms_apfRom[0][0] + fH*fSum);
for (int i2 = 1, iP2 = 4; i2 < i0; i2++, iP2 *= 4)
{
ms_apfRom[1][i2] =
(iP2*ms_apfRom[1][i2-1] - ms_apfRom[0][i2-1])/(iP2-1);
}
for (i1 = 0; i1 < i0; i1++)
ms_apfRom[0][i1] = ms_apfRom[1][i1];
}
return ms_apfRom[0][ms_iOrder-1];
}
double __fastcall TSegment::GetTFromS(double s)
{
// initial guess for Newton's method
int it=0;
double fTolerance= 0.001;
double fRatio = s/RombergIntegral(0,1);
double fOmRatio = 1.0 - fRatio;
double fTime = fOmRatio*0 + fRatio*1;
// for (int i = 0; i < iIterations; i++)
while (true)
{
it++;
if (it>10)
{
ErrorLog("Bad geometry: Too many iterations at "+Where(Point1));
//MessageBox(0,"Too many iterations","GetTFromS",MB_OK);
return fTime;
}
double fDifference = RombergIntegral(0,fTime) - s;
if ( ( fDifference>0 ? fDifference : -fDifference) < fTolerance )
return fTime;
fTime -= fDifference/GetFirstDerivative(fTime).Length();
}
// Newton's method failed. If this happens, increase iterations or
// tolerance or integration accuracy.
//return -1; //Ra: tu nigdy nie dojdzie
};
vector3 __fastcall TSegment::RaInterpolate(double t)
{//wyliczenie XYZ na krzywej Beziera z użyciem współczynników
return t*(t*(t*vA+vB)+vC)+Point1; //9 mnożeń, 9 dodawań
};
vector3 __fastcall TSegment::RaInterpolate0(double t)
{//wyliczenie XYZ na krzywej Beziera, na użytek liczenia długości nie jest dodawane Point1
return t*(t*(t*vA+vB)+vC); //9 mnożeń, 6 dodawań
};
double __fastcall TSegment::ComputeLength() //McZapkie-150503: dlugosc miedzy punktami krzywej
{//obliczenie długości krzywej Beziera za pomocą interpolacji odcinkami
//Ra: zamienić na liczenie rekurencyjne średniej z cięciwy i łamanej po kontrolnych
//Ra: koniec rekurencji jeśli po podziale suma długości nie różni się więcej niż 0.5mm od poprzedniej
//Ra: ewentualnie rozpoznać łuk okręgu płaskiego i liczyć ze wzoru na długość łuku
double t,l=0;
vector3 last=vector3(0,0,0); //długość liczona po przesunięciu odcinka do początku układu
vector3 tmp=Point2-Point1;
int m=20.0*tmp.Length(); //było zawsze do 10000, teraz jest liczone odcinkami po około 5cm
for (int i=1;i<=m;i++)
{
t=double(i)/double(m); //wyznaczenie parametru na krzywej z przedziału (0,1>
//tmp=Interpolate(t,p1,cp1,cp2,p2);
tmp=RaInterpolate0(t); //obliczenie punktu dla tego parametru
t=vector3(tmp-last).Length(); //obliczenie długości wektora
l+=t; //zwiększenie wyliczanej długości
last=tmp;
}
return (l);
}
const double fDirectionOffset=0.1; //długość wektora do wyliczenia kierunku
vector3 __fastcall TSegment::GetDirection(double fDistance)
{//takie toporne liczenie pochodnej dla podanego dystansu od Point1
double t1=GetTFromS(fDistance-fDirectionOffset);
if (t1<=0.0)
return (CPointOut-Point1); //na zewnątrz jako prosta
double t2=GetTFromS(fDistance+fDirectionOffset);
if (t2>=1.0)
return (Point1-CPointIn); //na zewnątrz jako prosta
return (FastGetPoint(t2)-FastGetPoint(t1));
}
vector3 __fastcall TSegment::FastGetDirection(double fDistance, double fOffset)
{//takie toporne liczenie pochodnej dla parametru 0.0÷1.0
double t1=fDistance-fOffset;
if (t1<=0.0)
return (CPointOut-Point1); //wektor na początku jest stały
double t2=fDistance+fOffset;
if (t2>=1.0)
return (Point2-CPointIn); //wektor na końcu jest stały
return (FastGetPoint(t2)-FastGetPoint(t1));
}
vector3 __fastcall TSegment::GetPoint(double fDistance)
{//wyliczenie współrzędnych XYZ na torze w odległości (fDistance) od Point1
if (bCurve)
{//można by wprowadzić uproszczony wzór dla okręgów płaskich
double t=GetTFromS(fDistance); //aproksymacja dystansu na krzywej Beziera
//return Interpolate(t,Point1,CPointOut,CPointIn,Point2);
return RaInterpolate(t);
}
else
{//wyliczenie dla odcinka prostego jest prostsze
double t=fDistance/fLength; //zerowych torów nie ma
return ((1.0-t)*Point1+(t)*Point2);
}
};
void __fastcall TSegment::RaPositionGet(double fDistance,vector3 &p,vector3 &a)
{//ustalenie pozycji osi na torze, przechyłki, pochylenia i kierunku jazdy
if (bCurve)
{//można by wprowadzić uproszczony wzór dla okręgów płaskich
double t=GetTFromS(fDistance); //aproksymacja dystansu na krzywej Beziera na parametr (t)
p=RaInterpolate(t);
a.x=(1.0-t)*fRoll1+(t)*fRoll2; //przechyłka w danym miejscu (zmienia się liniowo)
//pochodna jest 3*A*t^2+2*B*t+C
a.y=atan(t*(t*3.0*vA.y+vB.y+vB.y)+vC.y); //pochylenie krzywej (w pionie)
a.z=-atan2(t*(t*3.0*vA.x+vB.x+vB.x)+vC.x,t*(t*3.0*vA.z+vB.z+vB.z)+vC.z); //kierunek krzywej w planie
}
else
{//wyliczenie dla odcinka prostego jest prostsze
double t=fDistance/fLength; //zerowych torów nie ma
p=((1.0-t)*Point1+(t)*Point2);
a.x=(1.0-t)*fRoll1+(t)*fRoll2; //przechyłka w danym miejscu (zmienia się liniowo)
a.y=fStoop; //pochylenie toru prostego
a.z=fDirection; //kierunek toru w planie
}
};
vector3 __fastcall TSegment::FastGetPoint(double t)
{
//return (bCurve?Interpolate(t,Point1,CPointOut,CPointIn,Point2):((1.0-t)*Point1+(t)*Point2));
return (bCurve?RaInterpolate(t):((1.0-t)*Point1+(t)*Point2));
}
void __fastcall TSegment::RenderLoft(const vector6 *ShapePoints, int iNumShapePoints,
double fTextureLength, int iSkip, int iQualityFactor,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
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ć?
}
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;
}
}
else
{//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);
}
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();
}
};
void __fastcall 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,t2,t2step,oldt2,sp,oldsp;
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);
}
glEnd();
pos1= pos2;
parallel1= parallel2;
tv1=tv2;
a1= a2;
}
}
else
{//dla toru prostego
tv1=1.0;
s= 0;
i= 0;
// pos1= FastGetPoint( (5*iSkip)/fLength );
pos1= FastGetPoint_0();
dir=GetDirection();
//parallel1=CrossProduct(dir,vector3(0,1,0));
parallel1=Normalize(vector3(-dir.z,0.0,dir.x)); //wektor poprzeczny
step= 5;
a1= 0;
while (i<iSkip)
{
// step= SquareMagnitude(Global::GetCameraPosition()+pos);
i++;
s+= step;
if (s>fLength)
{
step-= (s-fLength);
s= fLength;
}
while (tv1<0.0) tv1+=1.0;
tv2=tv1-step/fTextureLength;
t= s/fLength;
pos2= FastGetPoint( t );
a2= double(i)/(iSkip);
glBegin(GL_TRIANGLE_STRIP);
for (j=0; j<iNumShapePoints; j++)
{
pt= parallel1*(ShapePoints1[j].x*a1+(ShapePoints2[j].x-fOffsetX)*(1.0-a1))+pos1;
pt.y+= ShapePoints1[j].y*a1+ShapePoints2[j].y*(1.0-a1);
glNormal3f(0.0f,1.0f,0.0f);
glTexCoord2f((ShapePoints1[j].z),tv1);
glVertex3f(pt.x,pt.y,pt.z);
pt= parallel1*(ShapePoints1[j].x*a2+(ShapePoints2[j].x-fOffsetX)*(1.0-a2))+pos2;
pt.y+= ShapePoints1[j].y*a2+ShapePoints2[j].y*(1.0-a2);
glNormal3f(0.0f,1.0f,0.0f);
glTexCoord2f(ShapePoints2[j].z,tv2);
glVertex3f(pt.x,pt.y,pt.z);
}
glEnd();
pos1= pos2;
tv1=tv2;
a1= a2;
}
}
};
void __fastcall TSegment::Render()
{
vector3 pt;
glBindTexture(GL_TEXTURE_2D, 0);
int i;
if (bCurve)
{
glColor3f(0,0,1.0f);
glBegin(GL_LINE_STRIP);
glVertex3f(Point1.x,Point1.y,Point1.z);
glVertex3f(CPointOut.x,CPointOut.y,CPointOut.z);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(Point2.x,Point2.y,Point2.z);
glVertex3f(CPointIn.x,CPointIn.y,CPointIn.z);
glEnd();
glColor3f(1.0f,0,0);
glBegin(GL_LINE_STRIP);
for (int i=0; i<=8; i++)
{
pt= FastGetPoint(double(i)/8.0f);
glVertex3f(pt.x,pt.y,pt.z);
}
glEnd();
}
else
{
glColor3f(0,0,1.0f);
glBegin(GL_LINE_STRIP);
glVertex3f(Point1.x,Point1.y,Point1.z);
glVertex3f(Point1.x+CPointOut.x,Point1.y+CPointOut.y,Point1.z+CPointOut.z);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(Point2.x,Point2.y,Point2.z);
glVertex3f(Point2.x+CPointIn.x,Point2.y+CPointIn.y,Point2.z+CPointIn.z);
glEnd();
glColor3f(0.5f,0,0);
glBegin(GL_LINE_STRIP);
glVertex3f(Point1.x+CPointOut.x,Point1.y+CPointOut.y,Point1.z+CPointOut.z);
glVertex3f(Point2.x+CPointIn.x,Point2.y+CPointIn.y,Point2.z+CPointIn.z);
glEnd();
}
}
void __fastcall 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 __fastcall 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++;
}
}
};
//---------------------------------------------------------------------------

104
Segment.h Normal file
View File

@@ -0,0 +1,104 @@
//---------------------------------------------------------------------------
#ifndef SegmentH
#define SegmentH
#include "VBO.h"
#include "dumb3d.h"
#include "Classes.h"
using namespace Math3D;
//110405 Ra: klasa punktów przekroju z normalnymi
class vector6 : public vector3
{//punkt przekroju wraz z wektorem normalnym
public:
vector3 n;
__fastcall vector6()
{x=y=z=n.x=n.z=0.0; n.y=1.0;};
__fastcall vector6(double a,double b,double c,double d,double e,double f)
//{x=a; y=b; z=c; n.x=d; n.y=e; n.z=f;};
{x=a; y=b; z=c; n.x=0.0; n.y=1.0; n.z=0.0;}; //Ra: bo na razie s¹ z tym problemy
__fastcall vector6(double a,double b,double c)
{x=a; y=b; z=c; n.x=0.0; n.y=1.0; n.z=0.0;};
};
class TSegment
{//aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
private:
vector3 Point1,CPointOut,CPointIn,Point2;
double fRoll1,fRoll2; //przechy³ka na koñcach
double fLength; //d³ugoœæ policzona
double *fTsBuffer; //wartoœci parametru krzywej dla równych odcinków
double fStep;
int iSegCount; //iloœæ odcinków do rysowania krzywej
double fDirection; //Ra: k¹t prostego w planie; dla ³uku k¹t od Point1
double fStoop; //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; //wskaŸnik na w³aœciciela
double fAngle[2]; //k¹ty zakoñczenia drogi na przejazdach
vector3 __fastcall GetFirstDerivative(double fTime);
double __fastcall RombergIntegral(double fA, double fB);
double __fastcall GetTFromS(double s);
vector3 __fastcall RaInterpolate(double t);
vector3 __fastcall 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;
//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)
__fastcall TSegment(TTrack *owner);
__fastcall ~TSegment();
bool __fastcall Init(vector3 NewPoint1,vector3 NewPoint2,double fNewStep,
double fNewRoll1=0,double fNewRoll2=0);
bool __fastcall Init(vector3 &NewPoint1,vector3 NewCPointOut,
vector3 NewCPointIn,vector3 &NewPoint2,double fNewStep,
double fNewRoll1=0,double fNewRoll2=0,bool bIsCurve=true);
inline double __fastcall ComputeLength(); //McZapkie-150503
inline vector3 __fastcall GetDirection1() {return bCurve?CPointOut-Point1:CPointOut;};
inline vector3 __fastcall GetDirection2() {return bCurve?CPointIn-Point2:CPointIn;};
vector3 __fastcall GetDirection(double fDistance);
vector3 __fastcall GetDirection() {return CPointOut;};
vector3 __fastcall FastGetDirection(double fDistance,double fOffset);
vector3 __fastcall GetPoint(double fDistance);
void __fastcall RaPositionGet(double fDistance,vector3 &p,vector3 &a);
vector3 __fastcall FastGetPoint(double t);
inline vector3 __fastcall FastGetPoint_0() {return Point1;};
inline vector3 __fastcall FastGetPoint_1() {return Point2;};
inline double __fastcall GetRoll(double s)
{
s/=fLength;
return ((1.0-s)*fRoll1+s*fRoll2);
}
void __fastcall GetRolls(double &r1,double &r2)
{//pobranie przechy³ek (do generowania trójk¹tów)
r1=fRoll1; r2=fRoll2;
}
void __fastcall RenderLoft(const vector6 *ShapePoints,int iNumShapePoints,
double fTextureLength,int iSkip=0,int iQualityFactor=1,vector3 **p=NULL,bool bRender=true);
void __fastcall RenderSwitchRail(const vector6 *ShapePoints1,const vector6 *ShapePoints2,
int iNumShapePoints,double fTextureLength,int iSkip=0,double fOffsetX=0.0f);
void __fastcall Render();
inline double __fastcall GetLength() {return fLength;};
void __fastcall MoveMe(vector3 pPosition)
{Point1+=pPosition;
Point2+=pPosition;
if (bCurve)
{CPointIn+=pPosition;
CPointOut+=pPosition;
}
}
int __fastcall RaSegCount() {return fTsBuffer?iSegCount:1;};
void __fastcall RaRenderLoft(CVertNormTex* &Vert,const vector6 *ShapePoints,int iNumShapePoints,
double fTextureLength,int iSkip=0,int iEnd=0,double fOffsetX=0.0);
void __fastcall RaAnimate(CVertNormTex* &Vert,const vector6 *ShapePoints,int iNumShapePoints,
double fTextureLength,int iSkip=0,int iEnd=0,double fOffsetX=0.0);
void __fastcall AngleSet(int i,double a) {fAngle[i]=a;};
void __fastcall Rollment(double w1,double w2); //poprawianie przechy³ki
};
//---------------------------------------------------------------------------
#endif

377
Sound.cpp Normal file
View File

@@ -0,0 +1,377 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#define STRICT
#include "Sound.h"
#include "Usefull.h"
#include "Globals.h"
//#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
char Directory[]= "sounds\\";
LPDIRECTSOUND TSoundsManager::pDS;
LPDIRECTSOUNDNOTIFY TSoundsManager::pDSNotify;
int TSoundsManager::Count= 0;
TSoundContainer *TSoundsManager::First=NULL;
__fastcall TSoundContainer::TSoundContainer( LPDIRECTSOUND pDS, char *Directory, char *strFileName, 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
Concurrent= NConcurrent;
Oldest= 0;
// strcpy(Name, strFileName);
strcpy(Name,Directory);
strcat(Name,strFileName);
CWaveSoundRead* pWaveSoundRead;
// Create a new wave file class
pWaveSoundRead = new CWaveSoundRead();
// Load the wave file
if (FAILED(pWaveSoundRead->Open(Name)))
if(FAILED(pWaveSoundRead->Open(strFileName)))
{
// SetFileUI( hDlg, TEXT("Bad wave file.") );
return;
ErrorLog("Missed sound: "+AnsiString(strFileName));
}
strcpy(Name,AnsiString(strFileName).LowerCase().c_str());
// Set up the direct sound buffer, and only request the flags needed
// since each requires some overhead and limits if the buffer can
// be hardware accelerated
DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
if (!Global::bInactivePause) //jeœli prze³¹czony w t³o ma nadal dzia³aæ
dsbd.dwFlags|=DSBCAPS_GLOBALFOCUS; //to dŸwiêki maj¹ byæ równie¿ s³yszalne
dsbd.dwBufferBytes = pWaveSoundRead->m_ckIn.cksize;
dsbd.lpwfxFormat = pWaveSoundRead->m_pwfx;
fSamplingRate=pWaveSoundRead->m_pwfx->nSamplesPerSec;
iBitsPerSample=pWaveSoundRead->m_pwfx->wBitsPerSample;
// pDSBuffer= (LPDIRECTSOUNDBUFFER*) malloc(Concurrent*sizeof(LPDIRECTSOUNDBUFFER));
// for (int i=0; i<Concurrent; i++)
// pDSBuffer[i]= NULL;
// Create the static DirectSound buffer
if( FAILED( hr = pDS->CreateSoundBuffer( &dsbd, &(DSBuffer), NULL ) ) )
//if (FAILED(pDS->CreateSoundBuffer(&dsbd,&(DSBuffer),NULL)))
return;
// Remember how big the buffer is
DWORD dwBufferBytes;
dwBufferBytes = dsbd.dwBufferBytes;
//----------------------------------------------------------
BYTE* pbWavData; // Pointer to actual wav data
UINT cbWavSize; // Size of data
VOID* pbData = NULL;
VOID* pbData2 = NULL;
DWORD dwLength;
DWORD dwLength2;
// The size of wave data is in pWaveFileSound->m_ckIn
INT nWaveFileSize = pWaveSoundRead->m_ckIn.cksize;
// Allocate that buffer.
pbWavData = new BYTE[ nWaveFileSize ];
if( NULL == pbWavData )
return ;//E_OUTOFMEMORY;
//if (FAILED(hr=pWaveSoundRead->Read( nWaveFileSize,pbWavData,&cbWavSize)))
if( FAILED( hr = pWaveSoundRead->Read( nWaveFileSize,
pbWavData,
&cbWavSize ) ) )
return ;
// Reset the file to the beginning
pWaveSoundRead->Reset();
// Lock the buffer down
//if (FAILED(hr=DSBuffer->Lock(0,dwBufferBytes,&pbData,&dwLength,&pbData2,&dwLength2,0)))
if( FAILED( hr = DSBuffer->Lock( 0, dwBufferBytes, &pbData, &dwLength,
&pbData2, &dwLength2, 0L ) ) )
return ;
// Copy the memory to it.
memcpy( pbData, pbWavData, dwBufferBytes );
// Unlock the buffer, we don't need it anymore.
DSBuffer->Unlock( pbData, dwBufferBytes, NULL, 0 );
pbData = NULL;
// 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;
};
};*/
};
__fastcall TSoundContainer::~TSoundContainer()
{
// for (int i=Concurrent-1; i>=0; i--)
// SAFE_RELEASE( pDSBuffer[i] );
// free(pDSBuffer);
while (!DSBuffers.empty())
{
SAFE_RELEASE(DSBuffers.top());
DSBuffers.pop();
}
SafeDelete( Next );
};
LPDIRECTSOUNDBUFFER __fastcall TSoundContainer::GetUnique(LPDIRECTSOUND pDS)
{
if (!DSBuffer) return NULL;
//jeœli siê dobrze zainicjowa³o
LPDIRECTSOUNDBUFFER buff;
pDS->DuplicateSoundBuffer(DSBuffer,&buff);
if (buff) DSBuffers.push(buff);
return DSBuffers.top();
};
__fastcall TSoundsManager::~TSoundsManager()
{
Free();
};
void __fastcall TSoundsManager::Free()
{
SafeDelete( First );
SAFE_RELEASE( pDS );
};
TSoundContainer* __fastcall TSoundsManager::LoadFromFile(char *Dir,char *Name,int Concurrent)
{
TSoundContainer *Tmp=First;
First=new TSoundContainer(pDS,Dir,Name,Concurrent);
First->Next=Tmp;
Count++;
return First; //albo NULL, jak nie wyjdzie (na razie zawsze wychodzi)
};
void __fastcall 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 __fastcall TSoundsManager::GetFromName(char *Name,bool Dynamic,float *fSamplingRate)
{//wyszukanie dŸwiêku w pamiêci albo wczytanie z pliku
AnsiString file;
if (Dynamic)
{//próba wczytania z katalogu pojazdu
file=Global::asCurrentDynamicPath+AnsiString(Name);
if (FileExists(file))
Name=file.c_str(); //nowa nazwa
else
Dynamic=false; //wczytanie z "sounds/"
}
TSoundContainer *Next=First;
DWORD dwStatus;
for (int i=0;i<Count;i++)
{
if (strcmp(Name,Next->Name)==0)
{
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);
else
Next=LoadFromFile(Directory,Name,1);
if (Next)
{//
if (fSamplingRate)
*fSamplingRate=Next->fSamplingRate; //czêstotliwoœæ
return Next->GetUnique(pDS);
}
ErrorLog("Missed sound: "+AnsiString(Name));
return (NULL);
};
void __fastcall TSoundsManager::RestoreAll()
{
TSoundContainer *Next= First;
HRESULT hr;
DWORD dwStatus;
for (int i=0; i<Count; i++)
{
if( FAILED( hr = Next->DSBuffer->GetStatus( &dwStatus ) ) );
// return hr;
if( dwStatus & DSBSTATUS_BUFFERLOST )
{
// Since the app could have just been activated, then
// DirectSound may not be giving us control yet, so
// the restoring the buffer may fail.
// If it does, sleep until DirectSound gives us control.
do
{
hr = Next->DSBuffer->Restore();
if( hr == DSERR_BUFFERLOST )
Sleep( 10 );
}
while ((hr=Next->DSBuffer->Restore())!=NULL);
// char *Name= Next->Name;
// int cc= Next->Concurrent;
// delete Next;
// Next= new TSoundContainer(pDS, Directory, Name, cc);
// if( FAILED( hr = FillBuffer() ) );
// return hr;
};
Next= Next->Next;
};
};
//void __fastcall TSoundsManager::Init(char *Name, int Concurrent)
//__fastcall TSoundsManager::TSoundsManager(HWND hWnd)
//void __fastcall TSoundsManager::Init(HWND hWnd, char *NDirectory)
void __fastcall TSoundsManager::Init(HWND hWnd)
{
First= NULL;
Count= 0;
pDS= NULL;
pDSNotify= NULL;
HRESULT hr; //=222;
LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
// strcpy(Directory, NDirectory);
// Create IDirectSound using the primary sound device
hr = DirectSoundCreate( NULL, &pDS, NULL );
if( hr!=DS_OK )
{
if (hr==DSERR_ALLOCATED)
return;
if (hr==DSERR_INVALIDPARAM)
return;
if (hr==DSERR_NOAGGREGATION)
return;
if (hr==DSERR_NODRIVER)
return;
if (hr==DSERR_OUTOFMEMORY)
return;
// hr=0;
};
// return ;
// Set coop level to DSSCL_PRIORITY
// if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) );
// return ;
pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );
// Get the primary buffer
DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
if (!Global::bInactivePause) //jeœli prze³¹czony w t³o ma nadal dzia³aæ
dsbd.dwFlags|=DSBCAPS_GLOBALFOCUS; //to dŸwiêki maj¹ byæ równie¿ s³yszalne
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = NULL;
if( FAILED( hr = pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
return ;
// Set primary buffer format to 22kHz and 16-bit output.
WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = 44100;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) )
return ;
SAFE_RELEASE( pDSBPrimary );
};
//---------------------------------------------------------------------------
#pragma package(smart_init)

61
Sound.h Normal file
View File

@@ -0,0 +1,61 @@
//---------------------------------------------------------------------------
#ifndef SoundH
#define SoundH
#include <stack>
#undef EOF
#include <objbase.h>
//#include <initguid.h>
//#include <commdlg.h>
#include <mmreg.h>
#include <dsound.h>
//#include "resource.h"
#include "WavRead.h"
typedef LPDIRECTSOUNDBUFFER PSound;
//inline __fastcall Playing(PSound Sound)
//{
//}
class TSoundContainer
{
public:
int Concurrent;
int Oldest;
char Name[80];
LPDIRECTSOUNDBUFFER DSBuffer;
float fSamplingRate; //czêstotliwoœæ odczytana z pliku
int iBitsPerSample; //ile bitów na próbkê
TSoundContainer *Next;
std::stack< LPDIRECTSOUNDBUFFER > DSBuffers;
LPDIRECTSOUNDBUFFER __fastcall GetUnique(LPDIRECTSOUND pDS);
__fastcall TSoundContainer(LPDIRECTSOUND pDS, char *Directory, char *strFileName, int NConcurrent);
__fastcall ~TSoundContainer();
};
class TSoundsManager
{
private:
static LPDIRECTSOUND pDS;
static LPDIRECTSOUNDNOTIFY pDSNotify;
// static char Directory[80];
static int Count;
static TSoundContainer *First;
static TSoundContainer* __fastcall LoadFromFile(char *Dir,char *Name,int Concurrent);
public:
// __fastcall TSoundsManager(HWND hWnd);
// static void __fastcall Init(HWND hWnd, char *NDirectory);
static void __fastcall Init(HWND hWnd);
__fastcall ~TSoundsManager();
static void __fastcall Free();
static void __fastcall Init(char *Name, int Concurrent);
static void __fastcall LoadSounds(char *Directory);
static LPDIRECTSOUNDBUFFER __fastcall GetFromName(char *Name,bool Dynamic,float *fSamplingRate=NULL);
static void __fastcall RestoreAll();
};
//---------------------------------------------------------------------------
#endif

518
Spline.cpp Normal file
View File

@@ -0,0 +1,518 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Geometry.h"
#include "Spline.h"
#include "usefull.h"
#include "maptextfile.hpp"
//#define asSplinesPatch AnsiString("Scenery\\")
bool __fastcall Connect(TKnot *k1, TKnot *k2)
{
if (k1 && k2)
{
k1->Next= k2;
k2->Prev= k1;
k1->InitLength();
return true;
}
else
return false;
}
#define Precision 10000
float __fastcall CurveLength(vector3 p1, vector3 cp1, vector3 cp2, vector3 p2)
{
float t,l=0;
vector3 tmp,last= p1;
for (int i=1; i<=Precision; i++)
{
t= float(i)/float(Precision);
tmp= Interpolate(t,p1,cp1,cp2,p2);
t= vector3(tmp-last).Length();
l+= t;
last= tmp;
}
return (l);
}
__fastcall TKnot::TKnot()
{
Next=Prev= NULL;
Length= -1;
IsCurve= false;
fLengthIn=fLengthOut= 0;
fRoll= 0;
bSwitchDirectionForward= false;
bSwitchDirectionBackward= false;
}
__fastcall TKnot::TKnot(int n)
{
bSwitchDirectionForward= false;
bSwitchDirectionBackward= false;
Next=Prev= NULL;
Length= -1;
IsCurve= false;
fLengthIn=fLengthOut= 0;
if (n>0)
{
Next= new TKnot(n-1);
Next->Prev= this;
}
}
__fastcall TKnot::~TKnot()
{
}
vector3 __fastcall TKnot::GetDirection(float t)
{
if (IsCurve)
{
vector3 v1= CPointOut-Point;
vector3 v2= Next->Point-Next->CPointIn; //BUGBUG
return v1*(1-t)+v2*(t);
}
else
return (Next->Point-Point);//Spline->Knots[KnotIndex].Point-Spline->Knots[KnotIndex].Point);
}
float __fastcall TKnot::GetTFromS(float s)
{
// initial guess for Newton's method
int it=0;
float fTolerance= 0.001;
float fRatio = s/RombergIntegral(0,1);
float fOmRatio = 1.0 - fRatio;
float fTime = fOmRatio*0 + fRatio*1;
// for (int i = 0; i < iIterations; i++)
while (true)
{
it++;
if (it>10)
MessageBox(0,"Too many iterations","TSpline->GetTFromS",MB_OK);
float fDifference = RombergIntegral(0,fTime) - s;
if ( ( fDifference>0 ? fDifference : -fDifference) < fTolerance )
return fTime;
fTime -= fDifference/GetFirstDerivative(fTime).Length();
}
// Newton's method failed. If this happens, increase iterations or
// tolerance or integration accuracy.
return -1;
}
bool __fastcall TKnot::Init(TKnot *NNext, TKnot *NPrev)
{
if (NNext!=NULL)
{
Next= NNext;
Next->Prev= this;
}
if (NPrev!=NULL)
{
Prev= NPrev;
Prev->Next= this;
}
}
bool __fastcall TKnot::InitCPoints()
{
if (Prev!=NULL)
if (Prev->IsCurve)
if (Next!=NULL)
{
if (!IsCurve)
{
CPointIn= Point-fLengthIn*Normalize(Next->Point-Point);
}
else
CPointIn= Point-fLengthIn*(Normalize(Normalize(Next->Point-Point)+Normalize(Point-Prev->Point)));
}
else
CPointIn= Point-fLengthIn*Normalize(Point-Prev->Point);
else
CPointIn= Prev->Point;
if (Next!=NULL)
if (IsCurve)
if (Prev!=NULL)
{
if (!Prev->IsCurve)
{
CPointOut= Point-fLengthOut*Normalize(Prev->Point-Point);
}
else
CPointOut= Point-fLengthOut*(Normalize(Normalize(Prev->Point-Point)+Normalize(Point-Next->Point)));
}
else;
// CPointOut= -fLengthOut*Normalize(Next->Point-Point);
else
CPointOut= Next->Point;
else
CPointOut= Point-fLengthOut*Normalize(Prev->Point-Point);
}
bool __fastcall TKnot::InitLength()
{
if (IsCurve)
if (Next)
Length= RombergIntegral(0,1);
else;
else
if (Next)
Length= (Point-Next->Point).Length();
return true;
}
vector3 TKnot::GetFirstDerivative(float fTime)
{
float fOmTime = 1.0 - fTime;
float fPowTime = fTime;
vector3 kResult = fOmTime*(CPointOut-Point);
int iDegreeM1 = 3 - 1;
float fCoeff = 2*fPowTime;
kResult = (kResult+fCoeff*(Next->CPointIn-CPointOut))*fOmTime;
fPowTime *= fTime;
kResult += fPowTime*(Next->Point-Next->CPointIn);
kResult *= 3;
return kResult;
}
float TKnot::RombergIntegral(float fA, float fB)
{
float fH = fB - fA;
const int ms_iOrder= 5;
float ms_apfRom[2][ms_iOrder];
ms_apfRom[0][0] = 0.5*fH*((GetFirstDerivative(fA).Length())+(GetFirstDerivative(fB).Length()));
for (int i0 = 2, iP0 = 1; i0 <= ms_iOrder; i0++, iP0 *= 2, fH *= 0.5)
{
// approximations via the trapezoid rule
float fSum = 0.0;
int i1;
for (i1 = 1; i1 <= iP0; i1++)
fSum += (GetFirstDerivative(fA + fH*(i1-0.5)).Length());
// Richardson extrapolation
ms_apfRom[1][0] = 0.5*(ms_apfRom[0][0] + fH*fSum);
for (int i2 = 1, iP2 = 4; i2 < i0; i2++, iP2 *= 4)
{
ms_apfRom[1][i2] =
(iP2*ms_apfRom[1][i2-1] - ms_apfRom[0][i2-1])/(iP2-1);
}
for (i1 = 0; i1 < i0; i1++)
ms_apfRom[0][i1] = ms_apfRom[1][i1];
}
return ms_apfRom[0][ms_iOrder-1];
}
//----------------------------------------------------------------------------//
__fastcall TSpline::TSpline()
{
// Closed= true;
// asName= "foo";
// Knots= NULL;
RootKnot= NULL;
iNumKnots= 0;
KnotsAllocated= false;
// Next=Prev= this;
}
__fastcall TSpline::TSpline(AnsiString asNName)
{
// Closed= true;
// asName= asNName;
// Knots= NULL;
RootKnot= NULL;
iNumKnots= 0;
KnotsAllocated= false;
// Next=Prev= this;
}
__fastcall TSpline::~TSpline()
{
// if (KnotsAllocated)
// SafeDeleteArray(Knots);
// SafeDelete(RootKnot);
TKnot *ck,*tk;
ck= RootKnot;
for (int i=0; i<iNumKnots; i++)
{
tk= ck;
ck= ck->Next;
SafeDelete(tk);
}
}
bool __fastcall TSpline::Create( int n, AnsiString asNName )
{
/*
// asName= asNName;
iNumKnots= n;
Knots= new TKnot[iNumKnots];
KnotsAllocated= true;
Knots[0].Prev= NULL;
Knots[iNumKnots-1].Next= NULL;
for (int i=1; i<iNumKnots; i++)
Knots[i].Init(NULL,Knots+i-1);
*/
}
bool __fastcall TSpline::AssignKnots( TKnot *FirstKnot, int n )
{
// iNumKnots= n;
// Knots= FirstKnot;
// KnotsAllocated= false;
}
int __fastcall TSpline::LoadFromFile( AnsiString FileName, TKnot *FirstKnot )
{
return false;
/*
int i;
iNumKnots= -1;
AnsiString buf;
buf.SetLength(255);
TMapTextfile *tf= new TMapTextfile();
tf->Open(asSceneryPatch+FileName,mmRead);
tf->ReadLn(buf);
if (buf==AnsiString("\"SPLINE\""))
{
tf->ReadLn(buf);
if (FirstKnot==NULL)
Create(buf.ToInt());
else
AssignKnots(FirstKnot,buf.ToInt());
TKnot *CurrentKnot= Knots;
// iNumKnots= buf.ToInt();
// Knots= new TKnot[iNumKnots];// malloc(*sizeof(TKnot));
DecimalSeparator= '.';
for (i=0; i<iNumKnots; i++)
{
tf->ReadLn(buf); CurrentKnot->Point.x= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->Point.z= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->Point.y= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->CPointIn.x= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->CPointIn.z= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->CPointIn.y= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->CPointOut.x= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->CPointOut.z= buf.ToDouble();
tf->ReadLn(buf); CurrentKnot->CPointOut.y= buf.ToDouble();
tf->ReadLn(buf);
// buf.Trim();
Knots[i].IsCurve= (buf!="#line ");
CurrentKnot= CurrentKnot->Next;
}
DecimalSeparator= ',';
CurrentKnot= Knots;
for (i=0; i<iNumKnots-1; i++)
{
// Knots[i].InitLength();
if (CurrentKnot->IsCurve)
{
CurrentKnot->Length= CurveLength(CurrentKnot->Point,CurrentKnot->CPointOut,CurrentKnot->Next->CPointIn,CurrentKnot->Next->Point);
}
else
{
CurrentKnot->CPointOut= 2*CurrentKnot->Point-CurrentKnot->CPointIn;
CurrentKnot->Next->CPointIn= CurrentKnot->Point;
CurrentKnot->Length= (CurrentKnot->Point-CurrentKnot->Next->Point).Length();
}
CurrentKnot= CurrentKnot->Next;
}
CurrentKnot->Length= -1;
}
tf->Close();
delete tf;
return (iNumKnots);
*/
}
int __fastcall TSpline::Load( TQueryParserComp *Parser, AnsiString asEndString )
{
TKnot *LastKnot= NULL;;
if (RootKnot!=NULL)
for (LastKnot= RootKnot; LastKnot->Next!=NULL; LastKnot= LastKnot->Next);
TKnot *tmp;
tmp= new TKnot(0);
tmp->Prev= LastKnot;
if (LastKnot!=NULL)
LastKnot->Next= tmp;
else
RootKnot= tmp;
LastKnot= tmp;
float tf,r,pr;
vector3 dir;
// asName= Parser->GetNextSymbol();
iNumKnots= 0;
do
{
LastKnot->fLengthIn= Parser->GetNextSymbol().ToDouble();
tf= Parser->GetNextSymbol().ToDouble();
LastKnot->Point.x= tf;
tf= Parser->GetNextSymbol().ToDouble();
LastKnot->Point.y= tf;
tf= Parser->GetNextSymbol().ToDouble();
LastKnot->Point.z= tf;
tf= Parser->GetNextSymbol().ToDouble();
LastKnot->fRoll= tf/180*M_PI;
LastKnot->fLengthOut= Parser->GetNextSymbol().ToDouble();
LastKnot->IsCurve= (LastKnot->fLengthOut!=0);
LastKnot->Next= new TKnot(0);
LastKnot->Next->Prev= LastKnot;
LastKnot= LastKnot->Next;
iNumKnots++;
} while (Parser->GetNextSymbol().LowerCase()!=asEndString && !Parser->EOF);
LastKnot->Prev->Next= NULL;
delete LastKnot;
if (RootKnot!=NULL)
for (LastKnot= RootKnot; LastKnot!=NULL; LastKnot= LastKnot->Next)
LastKnot->InitCPoints();
if (RootKnot!=NULL)
for (LastKnot= RootKnot; LastKnot!=NULL; LastKnot= LastKnot->Next)
LastKnot->InitLength();
}
float __fastcall TSpline::GetLength()
{
TKnot *tmp= RootKnot;
float l= 0;
for (int i=0; i<iNumKnots; i++)
{
l+= tmp->Length;
tmp= tmp->Next;
}
return l;
}
vector3 __fastcall TSpline::GetCenter()
{
TKnot *ck,*tk;
ck= RootKnot;
vector3 pt= vector3(0,0,0);
for (int i=0; i<iNumKnots; i++)
{
pt+= ck->Point;
ck= ck->Next;
}
if (iNumKnots>0)
pt/= iNumKnots;
}
TKnot* __fastcall TSpline::GetLastKnot()
{
TKnot *ck;
ck= RootKnot;
for (int i=0; i<iNumKnots-1; i++)
{
ck= ck->Next;
}
return ck;
}
bool __fastcall TSpline::Render()
{
TKnot *LastKnot= NULL;;
// if (RootKnot==NULL)
// RootKnot= Knots;
if (RootKnot!=NULL)
{
glBindTexture(GL_TEXTURE_2D, 0);
glBegin(GL_LINE_STRIP);
int i=0;
for (LastKnot= RootKnot; LastKnot!=NULL && i<iNumKnots; LastKnot= LastKnot->Next, i++)
// for (LastKnot= RootKnot; LastKnot!=NULL; LastKnot= LastKnot->Next)
glVertex3f(LastKnot->Point.x,LastKnot->Point.y,LastKnot->Point.z);
glEnd();
/*
if (RootKnot->Prev!=NULL)
{
glBindTexture(GL_TEXTURE_2D, 0);
glBegin(GL_LINE_STRIP);
glVertex3f(RootKnot->Point.x,RootKnot->Point.y,RootKnot->Point.z);
glVertex3f(RootKnot->Prev->Point.x,RootKnot->Prev->Point.y,RootKnot->Prev->Point.z);
glEnd();
}*/
}
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

89
Spline.h Normal file
View File

@@ -0,0 +1,89 @@
//---------------------------------------------------------------------------
#ifndef SplineH
#define SplineH
#include "dumb3d.h"
#include "QueryParserComp.hpp"
using namespace Math3D;
#define B1(t) (t*t*t)
#define B2(t) (3*t*t*(1-t))
#define B3(t) (3*t*(1-t)*(1-t))
#define B4(t) ((1-t)*(1-t)*(1-t))
#define Interpolate(t,p1,cp1,cp2,p2) (B4(t)*p1+B3(t)*cp1+B2(t)*cp2+B1(t)*p2)
class TKnot
{
public:
// inline bool __fastcall IsCurve() { return (!(Point==CPointIn)); };
// inline vector3 __fastcall GetDirection() { return (CPointOut-Point); };
__fastcall TKnot();
__fastcall TKnot(int n);
__fastcall ~TKnot();
inline float __fastcall GetRoll(float s)
{
if (Next)
{
s/= Length;
return ((1-s)*fRoll+(s)*Next->fRoll);
}
else
return fRoll;
// (Length-s) (s-Length)
}
vector3 __fastcall GetDirection(float t= 0);
inline vector3 __fastcall InterpolateSegm(float t) { return (Interpolate(t,Point,CPointOut,Next->CPointIn,Next->Point) ); };
float __fastcall GetTFromS(float s);
bool __fastcall Init(TKnot *NNext, TKnot *NPrev);
bool __fastcall InitCPoints();
bool __fastcall InitLength();
vector3 Point,CPointIn,CPointOut;
float fRoll;
bool IsCurve;
float Length;
TKnot *Next,*Prev;
float fLengthIn,fLengthOut;
bool bSwitchDirectionForward;
bool bSwitchDirectionBackward;
private:
vector3 GetFirstDerivative(float fTime);
float RombergIntegral (float fA, float fB);
};
class TSpline
{
public:
__fastcall TSpline();
__fastcall TSpline(AnsiString asNName);
__fastcall ~TSpline();
bool __fastcall Create( int n, AnsiString asNName="foo" );
bool __fastcall AssignKnots( TKnot *FirstKnot, int n );
int __fastcall LoadFromFile( AnsiString FileName, TKnot *FirstKnot = NULL );
int __fastcall Load( TQueryParserComp *Parser, AnsiString asEndString="endspline" );
float __fastcall GetLength();
vector3 __fastcall GetCenter();
TKnot* __fastcall GetLastKnot();
bool __fastcall Render();
// inline int NextIndex(int n) { return (n<KnotsCount-1 ? n+1 : 0); };
// inline vector3 InterpolateSegm(int i, float t) { return (Interpolate(t,Knots[i].Point,Knots[i].CPointOut,Knots[NextIndex(i)].CPointIn,Knots[NextIndex(i)].Point) ); };
// inline vector3 InterpolateSegm(TKnot *Knot, float t) { return (Interpolate(t,Knots[i].Point,Knots[i].CPointOut,Knots[NextIndex(i)].CPointIn,Knots[NextIndex(i)].Point) ); };
// bool Closed;
// AnsiString asName;
// TKnot *Knots;
TKnot *RootKnot;
bool KnotsAllocated;
int iNumKnots;
// TSpline *Next,*Prev;
// TKnot Next,Prev;
private:
};
bool __fastcall Connect(TKnot *k1, TKnot *k2);
//---------------------------------------------------------------------------
#endif

79
Spring.cpp Normal file
View File

@@ -0,0 +1,79 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#include "opengl/glew.h"
#include "opengl/glut.h"
#pragma hdrstop
#include "Spring.h"
#include "Usefull.h"
__fastcall TSpring::TSpring()
{
vForce1=vForce2= vector3(0,0,0);
Ks= 0;
Kd= 0;
restLen= 0;
}
__fastcall TSpring::~TSpring()
{
}
void __fastcall TSpring::Init(double nrestLen, double nKs, double nKd)
{
Ks= nKs;
Kd= nKd;
restLen= nrestLen;
}
bool __fastcall TSpring::ComputateForces(vector3 pPosition1, vector3 pPosition2)
{
double dist, Hterm, Dterm;
vector3 springForce,deltaV,deltaP;
// p1 = &system[spring->p1];
// p2 = &system[spring->p2];
// VectorDifference(&p1->pos,&p2->pos,&deltaP); // Vector distance
deltaP= pPosition1 - pPosition2;
// dist = VectorLength(&deltaP); // Magnitude of deltaP
dist = deltaP.Length();
if (dist==0)
{
vForce1=vForce2=vector3(0,0,0);
return false;
}
// Hterm = (dist - spring->restLen) * spring->Ks; // Ks * (dist - rest)
Hterm= (dist - restLen) * Ks; // Ks * (dist - rest)
// VectorDifference(&p1->v,&p2->v,&deltaV); // Delta Velocity Vector
deltaV= pPosition1 - pPosition2;
// Dterm = (DotProduct(&deltaV,&deltaP) * spring->Kd) / dist; // Damping Term
//Dterm = (DotProduct(deltaV,deltaP) * Kd) / dist;
Dterm= 0;
// ScaleVector(&deltaP,1.0f / dist, &springForce); // Normalize Distance Vector
// ScaleVector(&springForce,-(Hterm + Dterm),&springForce); // Calc Force
springForce= deltaP/dist*(-(Hterm + Dterm));
// VectorSum(&p1->f,&springForce,&p1->f); // Apply to Particle 1
// VectorDifference(&p2->f,&springForce,&p2->f); // - Force on Particle 2
vForce1= springForce;
vForce2= springForce;
return true;
}
void __fastcall TSpring::Render()
{
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

38
Spring.h Normal file
View File

@@ -0,0 +1,38 @@
//---------------------------------------------------------------------------
#ifndef ParticlesH
#define ParticlesH
#define STATIC_THRESHOLD 0.17f
//efine STATIC_THRESHOLD 0.03f
const double m_Kd = 0.02f; // DAMPING FACTOR
const double m_Kr = 0.8f; // 1.0 = SUPERBALL BOUNCE 0.0 = DEAD WEIGHT
const double m_Ksh = 5.0f; // HOOK'S SPRING CONSTANT
const double m_Ksd = 0.1f; // SPRING DAMPING CONSTANT
const double m_Csf = 0.9f; // Default Static Friction
const double m_Ckf = 0.7f; // Default Kinetic Friction
#include "dumb3d.h"
using namespace Math3D;
class TSpring
{
public:
__fastcall TSpring();
__fastcall ~TSpring();
// void __fastcall Init(TParticnp1, TParticle *np2, double nKs= 0.5f, double nKd= 0.002f, double nrestLen= -1.0f);
void __fastcall Init(double nrestLen, double nKs= 0.5f, double nKd= 0.002f);
bool __fastcall ComputateForces(vector3 pPosition1, vector3 pPosition2);
void __fastcall Render();
vector3 vForce1,vForce2;
double restLen; // LENGTH OF SPRING AT REST
double Ks; // SPRING CONSTANT
double Kd; // SPRING DAMPING
private:
};
//---------------------------------------------------------------------------
#endif

835
Texture.cpp Normal file
View File

@@ -0,0 +1,835 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak and others
*/
#include <iostream>
#include <fstream>
#include "opengl/glew.h"
#include <ddraw>
#include "system.hpp"
#include "classes.hpp"
#include "stdio.h"
#pragma hdrstop
#include "Usefull.h"
#include "Texture.h"
#include "TextureDDS.h"
#include "logs.h"
#include "Globals.h"
#include "io.h"
TTexturesManager::Alphas TTexturesManager::_alphas;
TTexturesManager::Names TTexturesManager::_names;
void TTexturesManager::Init()
{
};
TTexturesManager::Names::iterator TTexturesManager::LoadFromFile(std::string fileName,int filter)
{
std::string message("Loading - texture: ");
std::string realFileName(fileName);
std::ifstream file(fileName.c_str());
//Ra: niby bez tego jest lepiej, ale dzia³a gorzej, wiêc przywrócone jest oryginalne
if (!file.is_open())
realFileName.insert(0,szTexturePath);
else
file.close();
//char* cFileName = const_cast<char*>(fileName.c_str());
message += realFileName;
WriteLog(message.c_str()); //Ra: chybaa mia³o byæ z komunikatem z przodu, a nie tylko nazwa
size_t pos = fileName.rfind('.');
std::string ext(fileName, pos + 1, std::string::npos);
AlphaValue texinfo;
if (ext=="tga")
texinfo=LoadTGA(realFileName,filter);
else if (ext=="tex")
texinfo=LoadTEX(realFileName);
else if (ext=="bmp")
texinfo=LoadBMP(realFileName);
else if (ext=="dds")
texinfo=LoadDDS(realFileName,filter);
_alphas.insert(texinfo); //zapamiêtanie stanu przezroczystoœci tekstury - mo¿na by tylko przezroczyste
std::pair<Names::iterator, bool> ret = _names.insert(std::make_pair(fileName, texinfo.first));
if (!texinfo.first)
{
WriteLog("Failed");
ErrorLog("Missed texture: "+AnsiString(realFileName.c_str()));
return _names.end();
};
_alphas.insert(texinfo);
ret=_names.insert(std::make_pair(fileName,texinfo.first)); //dodanie tekstury do magazynu (spisu nazw)
//WriteLog("OK"); //Ra: "OK" nie potrzeba, samo "Failed" wystarczy
return ret.first;
};
struct ReplaceSlash
{
const char operator()(const char input)
{
return input == '/' ? '\\' : input;
}
};
GLuint TTexturesManager::GetTextureID(char* dir,char* where,std::string fileName,int filter)
{//ustalenie numeru tekstury, wczytanie jeœli nie jeszcze takiej nie by³o
/*
// Ra: niby tak jest lepiej, ale dzia³a gorzej, wiêc przywrócone jest oryginalne
//najpierw szukamy w katalogu, z którego wywo³ywana jest tekstura, potem z wy¿szego
//Ra: przerobiæ na wyszukiwanie w drzewie nazw, do którego zapisywaæ np. rozmiary, przezroczystoœæ
//Ra: ustalaæ, które tekstury mo¿na wczytaæ ju¿ w trakcie symulacji
size_t pos=fileName.find(':'); //szukamy dwukropka
if (pos!=std::string::npos) //po dwukropku mog¹ byæ podane dodatkowe informacje
fileName=fileName.substr(0,pos); //niebêd¹ce nazw¹ tekstury
std::transform(fileName.begin(),fileName.end(),fileName.begin(),ReplaceSlash()); //zamiana "/" na "\"
//jeœli bie¿aca œcie¿ka do tekstur nie zosta³a dodana to dodajemy domyœln¹
//if (fileName.find('\\')==std::string::npos) //bz sensu
// fileName.insert(0,szDefaultTexturePath);
//najpierw szukamy w podanym katalogu, potem w domyœlnym
Names::iterator iter;
std::ifstream file;
if ((fileName.find('.')==fileName.npos)?true:(fileName.rfind('.')<fileName.rfind('\\'))) //pierwsza kropka od prawej jest wczeœniej ni¿ "\"
{//Ra: jeœli nie ma kropki w nazwie pliku, wypróbowanie rozszerzeñ po kolei, zaczynaj¹c od domyœlnego
fileName.append("."); //kropkê trzeba dodaæ na pewno, resztê trzeba próbowaæ
std::string test; //zmienna robocza
for (int i=0;i<4;++i)
{//najpierw szukamy w magazynie
test=fileName;
if (where) test.insert(0,where); //œcie¿ka obiektu wywo³uj¹cego
test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeñ
iter=_names.find(test); //czy mamy ju¿ w magazynie?
if (iter!=_names.end())
return iter->second; //znalezione!
if (dir)
{//mo¿e we wskazanym katalogu?
test=fileName;
test.insert(0,dir); //jeszcze próba z dodatkow¹ œcie¿k¹
test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeñ
iter=_names.find(test); //czy mamy ju¿ w magazynie?
if (iter!=_names.end())
return iter->second; //znalezione!
}
//}
//for (int i=0;i<4;++i)
//{//w magazynie nie ma, to sprawdzamy na dysku
test=fileName;
if (where) test.insert(0,where); //œcie¿ka obiektu wywo³uj¹cego
test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeñ
file.open(test.c_str());
if (!file.is_open())
{test=fileName;
if (dir) test.insert(0,dir); //próba z dodatkow¹ œcie¿k¹
test.append(Global::szDefaultExt[i]); //dodanie jednego z kilku rozszerzeñ
file.open(test.c_str());
}
if (file.is_open())
{//jak znaleziony, to plik zostaje otwarty
fileName=test; //zapamiêtanie znalezionego rozszerzenia
break; //wyjœcie z pêtli na etapie danego rozszerzenia
}
}
}
else
{//gdy jest kropka, to rozszerzenie jest jawne
std::string test; //zmienna robocza
//najpierw szukamy w magazynie
test=fileName;
if (where) test.insert(0,where); //œcie¿ka obiektu wywo³uj¹cego
iter=_names.find(test); //czy mamy ju¿ w magazynie?
if (iter!=_names.end())
return iter->second; //znalezione!
test=fileName;
if (dir) test.insert(0,dir); //jeszcze próba z dodatkow¹ œcie¿k¹
iter=_names.find(test); //czy mamy ju¿ w magazynie?
if (iter!=_names.end())
return iter->second; //znalezione!
//w magazynie nie ma, to sprawdzamy na dysku
test=fileName;
if (where) test.insert(0,where); //œcie¿ka obiektu wywo³uj¹cego
file.open(test.c_str());
if (!file.is_open())
{//jak znaleziony, to plik zostaje otwarty
test=fileName;
if (dir) test.insert(0,dir); //próba z dodatkow¹ œcie¿k¹
file.open(test.c_str());
if (file.is_open())
fileName=test; //ustalenie nowej nazwy
}
}
if (file.is_open())
{//plik pozostaje otwarty, gdy znaleziono na dysku
file.close(); //mo¿na ju¿ zamkn¹æ
iter=LoadFromFile(fileName,filter); //doda siê do magazynu i zwróci swoj¹ pozycjê
}
*/
size_t pos=fileName.find(':'); //szukamy dwukropka
if (pos!=std::string::npos) //po dwukropku mog¹ byæ podane dodatkowe informacje
fileName=fileName.substr(0,pos); //niebêd¹ce nazw¹ tekstury
pos=fileName.find('|'); //szukamy separatora tekstur
if (pos!=std::string::npos) //po | mo¿e byæ nazwa kolejnej tekstury
fileName=fileName.substr(0,pos); //i trzeba to obci¹æ
std::transform(fileName.begin(),fileName.end(),fileName.begin(),ReplaceSlash());
//jeœli bie¿aca œcie¿ka do tekstur nie zosta³a dodana to dodajemy domyœln¹
if (fileName.find('\\')==std::string::npos)
fileName.insert(0,szTexturePath);
Names::iterator iter;
if (fileName.find('.')==std::string::npos)
{//Ra: wypróbowanie rozszerzeñ po kolei, zaczynaj¹c od domyœlnego
fileName.append("."); //kropka bêdze na pewno, resztê trzeba próbowaæ
std::string test; //zmienna robocza
for (int i=0;i<4;++i)
{//najpierw szukamy w magazynie
test=fileName;
test.append(Global::szDefaultExt[i]);
iter=_names.find(fileName); //czy mamy ju¿ w magazynie?
if (iter!=_names.end())
return iter->second; //znalezione!
test.insert(0,szTexturePath); //jeszcze próba z dodatkow¹ œcie¿k¹
iter=_names.find(fileName); //czy mamy ju¿ w magazynie?
if (iter!=_names.end())
return iter->second; //znalezione!
}
for (int i=0;i<4;++i)
{//w magazynie nie ma, to sprawdzamy na dysku
test=fileName;
test.append(Global::szDefaultExt[i]);
std::ifstream file(test.c_str());
if (!file.is_open())
{test.insert(0,szTexturePath);
file.open(test.c_str());
}
if (file.is_open())
{
fileName.append(Global::szDefaultExt[i]); //dopisanie znalezionego
file.close();
break; //wyjœcie z pêtli na etapie danego rozszerzenia
}
}
}
iter=_names.find(fileName); //czy mamy ju¿ w magazynie
if (iter==_names.end())
iter=LoadFromFile(fileName,filter);
return (iter!=_names.end()?iter->second:0);
};
bool TTexturesManager::GetAlpha(GLuint id)
{//atrybut przezroczystoœci dla tekstury o podanym numerze (id)
Alphas::iterator iter=_alphas.find(id);
return (iter!=_alphas.end()?iter->second:false);
}
TTexturesManager::AlphaValue TTexturesManager::LoadBMP(std::string fileName)
{
AlphaValue fail(0, false);
std::ifstream file(fileName.c_str(), std::ios::binary);
if (!file.is_open())
{
//file.close();
return fail;
};
BITMAPFILEHEADER header;
size_t bytes;
file.read((char*) &header, sizeof(BITMAPFILEHEADER));
if(file.eof())
{
file.close();
return fail;
}
// Read in bitmap information structure
BITMAPINFO info;
long infoSize = header.bfOffBits - sizeof(BITMAPFILEHEADER);
file.read((char*) &info, infoSize);
if(file.eof())
{
file.close();
return fail;
};
GLuint width = info.bmiHeader.biWidth;
GLuint height = info.bmiHeader.biHeight;
unsigned long bitSize = info.bmiHeader.biSizeImage;
if(!bitSize)
bitSize = (width * info.bmiHeader.biBitCount + 7) / 8 * height;
GLubyte* data = new GLubyte[bitSize];
file.read((char*) data, bitSize);
if(file.eof())
{
delete[] data;
file.close();
return fail;
};
file.close();
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// This is specific to the binary format of the data read in.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0,
GL_BGR_EXT, GL_UNSIGNED_BYTE, data);
delete[] data;
return std::make_pair(id, false);
};
TTexturesManager::AlphaValue TTexturesManager::LoadTGA(std::string fileName,int filter)
{
AlphaValue fail(0,false);
int writeback=-1; //-1 plik jest OK, >=0 - od którego bajtu zapisaæ poprawiony plik
GLubyte TGACompheader[]={0,0,10,0,0,0,0,0,0,0,0,0}; //uncompressed TGA header
GLubyte TGAcompare[12]; //used to compare TGA header
GLubyte header[6]; //first 6 useful bytes from the header
std::fstream file(fileName.c_str(),std::ios::binary|std::ios::in);
file.read((char*)TGAcompare,sizeof(TGAcompare));
file.read((char*)header,sizeof(header));
//std::cout << file.tellg() << std::endl;
if (file.eof())
{
file.close();
return fail;
};
bool compressed=(memcmp(TGACompheader,TGAcompare,sizeof(TGACompheader))==0);
GLint width =header[1]*256+header[0]; //determine the TGA width (highbyte*256+lowbyte)
GLint height=header[3]*256+header[2]; //determine the TGA height (highbyte*256+lowbyte)
// check if width, height and bpp is correct
if ( !width || !height || (header[4]!=24 && header[4]!=32))
{
WriteLog("Bad texture: "+AnsiString(fileName.c_str())+" has wrong header or bits per pixel");
file.close();
return fail;
};
{//sprawdzenie prawid³owoœci rozmiarów
int i,j;
for (i=width,j=0;i;i>>=1) if (i&1) ++j;
if (j==1)
for (i=height,j=0;i;i>>=1) if (i&1) ++j;
if (j!=1) WriteLog("Bad texture: "+AnsiString(fileName.c_str())+" is "+AnsiString(width)+"×"+AnsiString(height));
}
GLuint bpp=header[4]; //grab the TGA's bits per pixel (24 or 32)
GLuint bytesPerPixel=bpp/8; // divide by 8 to get the bytes per pixel
GLuint imageSize=width*height*bytesPerPixel; //calculate the memory required for the TGA data
GLubyte *imageData=new GLubyte[imageSize]; //reserve memory to hold the TGA data
if (!compressed)
{//WriteLog("Not compressed.");
file.read(imageData,imageSize);
if (file.eof())
{
delete[] imageData;
file.close();
return fail;
};
}
else
{//skompresowany plik TGA
GLuint filesize; //current byte
GLuint colorbuffer[1]; // Storage for 1 pixel
file.seekg(0,ios::end); //na koniec
filesize=(int)file.tellg()-18; //rozmiar bez nag³ówka
file.seekg(18,ios::beg); //ponownie za nag³ówkiem
GLubyte *copyto=imageData; //gdzie wstawiaæ w buforze
GLubyte *copyend=imageData+imageSize; //za ostatnim bajtem bufora
GLubyte *copyfrom=imageData+imageSize-filesize; //gdzie jest pocz¹tek
int chunkheader=0; //Ra: bêdziemy wczytywaæ najm³odszy bajt
if (filesize<imageSize) //jeœli po kompresji jest mniejszy ni¿ przed
{//Ra: nowe wczytywanie skompresowanych: czytamy ca³e od razu, dekompresja w pamiêci
GLuint copybytes;
file.read(copyfrom,filesize); //wczytanie reszty po nag³ówku
//najpierw trzeba ustaliæ, ile skopiowanych pikseli jest na samym koñcu
copyto=copyfrom; //roboczo przelatujemy wczytane dane
copybytes=0; //licznik bajtów obrazka
while (copybytes<imageSize)
{
chunkheader=(unsigned char)*copyto; //jeden bajt, pozosta³e zawsze zerowe
copyto+=1+bytesPerPixel; //bajt licznika oraz jeden piksel jest zawsze
copybytes+=(1+(chunkheader&127))*bytesPerPixel; //iloϾ pikseli
if (chunkheader<128) //jeœli kopiowanie, pikseli jest wiêcej
copyto+=(chunkheader)*bytesPerPixel; //rozmiar kopiowanego obszaru (bez jednego piksela)
}
if (copybytes>imageSize)
{//nie ma prawa byæ wiêksze
WriteLog("Compression error");
delete[] imageData;
file.close();
return fail;
}
//na koñcu mog¹ byæ œmieci
int extraend=copyend-copyto; //d³ugoœæ œmieci na koñcu
if (extraend>0)
{//przesuwamy bufor do koñca obszaru dekompresji
WriteLog("Extra bytes: "+AnsiString(extraend));
memmove(copyfrom+extraend,copyfrom,filesize-extraend);
copyfrom+=extraend;
file.close();
filesize-=extraend; //to chyba nie ma znaczenia
if (Global::iModifyTGA&2) //flaga obcinania œmieci
{//najlepiej by by³o obci¹æ plik, ale fstream tego nie potrafi
int handle;
for (unsigned int i=0;i<fileName.length();++i)
if (fileName[i]=='/')
fileName[i]=='\\'; //bo to Windows
WriteLog("Truncating extra bytes");
handle=open(fileName.c_str(),O_RDWR|O_BINARY);
chsize(handle,18+filesize); //obciêcie œmieci
close(handle);
extraend=0; //skoro obciêty, to siê ju¿ nie liczy
}
file.open(fileName.c_str(),std::ios::binary|std::ios::in);
}
if (chunkheader<128) //jeœli ostatnie piksele s¹ kopiowane
copyend-=(1+chunkheader)*bytesPerPixel; //bajty kopiowane na koñcu nie podlegaj¹ce dekompresji
else
copyend-=bytesPerPixel; //ostatni piksel i tak siê nie zmieni
copyto=imageData; //teraz bêdzie wype³nianie od pocz¹tku obszaru
while (copyto<copyend)
{
chunkheader=(unsigned char)*copyfrom; //jeden bajt, pozosta³e zawsze zerowe
if (copyto>copyfrom)
{//jeœli piksele maj¹ byæ kopiowane, to mo¿liwe jest przesuniêcie ich o 1 bajt, na miejsce licznika
filesize=(imageData+imageSize-copyto)/bytesPerPixel; //ile pikseli pozosta³o do koñca
//WriteLog("Decompression buffer overflow at pixel "+AnsiString((copyto-imageData)/bytesPerPixel)+"+"+AnsiString(filesize));
//pozycjê w pliku trzeba by zapamietaæ i po wczytaniu reszty pikseli star¹ metod¹
//zapisaæ od niej dane od (copyto), poprzedzone bajtem o wartoœci (filesize-1)
writeback=imageData+imageSize+extraend-copyfrom; //ile bajtów skompresowanych zosta³o do koñca
copyfrom=copyto; //adres piksela do zapisania
file.seekg(-writeback,ios::end); //odleg³oœæ od koñca (ujemna)
if ((filesize>128)||!(Global::iModifyTGA&4)) //gdy za du¿o pikseli albo wy³¹czone
writeback=-1; //zapis mo¿liwe jeœli iloœæ problematycznych pikseli nie przekaracza 128
break; //bufor siê zatka³, dalej w ten sposób siê nie da
}
if (chunkheader<128)
{//dla nag³ówka < 128 mamy podane ile pikseli przekopiowaæ minus 1
copybytes=(++chunkheader)*bytesPerPixel; //rozmiar kopiowanego obszaru
memcpy(copyto,++copyfrom,copybytes); //skopiowanie tylu bajtów
copyto+=copybytes;
copyfrom+=copybytes;
}
else
{//chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
chunkheader-=127;
//copy the color into the image data as many times as dictated
if (bytesPerPixel==4)
{//przy czterech bajtach powinno byæ szybsze u¿ywanie int
__int32 *ptr=(__int32*)(copyto); //wskaŸnik na int
__int32 bgra=*((__int32*)++copyfrom); //kolor wype³niaj¹cy (4 bajty)
for (int counter=0;counter<chunkheader;counter++)
*ptr++=bgra;
copyto=(char*)(ptr); //rzutowanie, ¿eby nie dodawaæ
copyfrom+=4;
}
else
{colorbuffer[0]=*((int*)(++copyfrom)); //pobranie koloru (3 bajty)
for (int counter=0;counter<chunkheader;counter++)
{ // by the header
memcpy(copyto,colorbuffer,3);
copyto+=3;
}
copyfrom+=3;
}
}
} //while (copyto<copyend)
}
else
{WriteLog("Compressed file is larger than uncompressed!");
if (Global::iModifyTGA&1)
writeback=0; //no zapisaæ ten krótszy zaczynajac od pocz¹tku...
}
//if (copyto<copyend) WriteLog("Slow loader...");
while (copyto<copyend)
{//Ra: stare wczytywanie skompresowanych, z nadu¿ywaniem file.read()
//równie¿ wykonywane, jeœli dekompresja w buforze przekroczy jego rozmiar
file.read((char*)&chunkheader,1); //jeden bajt, pozosta³e zawsze zerowe
if (file.eof())
{
MessageBox(NULL,"Could not read RLE header","ERROR",MB_OK); //display error
delete[] imageData;
file.close();
return fail;
};
if (chunkheader<128)
{//if the header is < 128, it means the that is the number of RAW color packets minus 1
chunkheader++; //add 1 to get number of following color values
file.read(copyto,chunkheader*bytesPerPixel);
copyto+=chunkheader*bytesPerPixel;
}
else
{//chunkheader>128 RLE data, next color reapeated (chunkheader-127) times
chunkheader-=127;
file.read((char*)colorbuffer,bytesPerPixel);
//copy the color into the image data as many times as dictated
if (bytesPerPixel==4)
{//przy czterech bajtach powinno byæ szybsze u¿ywanie int
__int32 *ptr=(__int32*)(copyto),bgra=*((__int32*)colorbuffer);
for (int counter=0;counter<chunkheader;counter++)
*ptr++=bgra;
copyto=(char*)(ptr); //rzutowanie, ¿eby nie dodawaæ
}
else
for (int counter=0;counter<chunkheader;counter++)
{ // by the header
memcpy(copyto,colorbuffer,bytesPerPixel);
copyto+=bytesPerPixel;
}
}
} //while (copyto<copyend)
if (writeback>=0)
{//zapisanie pliku
file.close(); //tamten zamykamy, bo by³ tylko do odczytu
if (writeback)
{//zapisanie samej koñcówki pliku, która utrudnia dekompresjê w buforze
WriteLog("Rewriting end of file...");
chunkheader=filesize-1; //licznik jest o 1 mniejszy
file.open(fileName.c_str(),std::ios::binary|std::ios::out|std::ios::in);
file.seekg(-writeback,ios::end); //odleg³oœæ od koñca (ujemna)
file.write((char*)&chunkheader,1); //zapisanie licznika
file.write(copyfrom,filesize*bytesPerPixel); //piksele bez kompresji
}
else
{//zapisywanie ca³oœci pliku, bêdzie krótszy, wiêc trzeba usun¹æ go w ca³oœci
WriteLog("Writing uncompressed file...");
TGAcompare[2]=2; //bez kompresji
file.open(fileName.c_str(),std::ios::binary|std::ios::out|std::ios::trunc);
file.write((char*)TGAcompare,sizeof(TGAcompare));
file.write((char*)header,sizeof(header));
file.write(imageData,imageSize);
}
}
};
file.close(); //plik zamykamy dopiero na samym koñcu
bool alpha = (bpp == 32);
bool hash = (fileName.find('#') != std::string::npos); //true gdy w nazwie jest "#"
bool dollar = (fileName.find('$') == std::string::npos); //true gdy w nazwie nie ma "$"
size_t pos=fileName.rfind('%'); //ostatni % w nazwie
if (pos!=std::string::npos)
if (pos<fileName.size())
{filter=(int)fileName[pos+1]-'0'; //zamiana cyfry za % na liczbê
if ((filter<0)||(filter>10)) filter=-1; //jeœli nie jest cyfr¹
}
if (!alpha&&!hash&&dollar&&(filter<0))
filter=Global::iDefaultFiltering; //dotyczy tekstur TGA bez kana³u alfa
//ewentualne przeskalowanie tekstury do dopuszczalnego rozumiaru
GLint w=width,h=height;
if (width>Global::iMaxTextureSize) width=Global::iMaxTextureSize; //ogranizczenie wielkoœci
if (height>Global::iMaxTextureSize) height=Global::iMaxTextureSize;
if ((w!=width)||(h!=height))
{//przeskalowanie tekstury, ¿eby siê nie wyœwietla³a jako bia³a
GLubyte* imgData=new GLubyte[width*height*bytesPerPixel]; //nowy rozmiar
gluScaleImage(bytesPerPixel==3?GL_RGB:GL_RGBA,w,h,GL_UNSIGNED_BYTE,imageData,width,height,GL_UNSIGNED_BYTE,imgData);
delete imageData; //usuniêcie starego
imageData=imgData;
}
GLuint id=CreateTexture(imageData,(alpha?GL_BGRA:GL_BGR),width,height,alpha,hash,dollar,filter);
delete[] imageData;
++Global::iTextures;
return std::make_pair(id,alpha);
};
TTexturesManager::AlphaValue TTexturesManager::LoadTEX(std::string fileName)
{
AlphaValue fail(0, false);
std::ifstream file(fileName.c_str(), ios::binary);
char head[5];
file.read(head, 4);
head[4] = 0;
bool alpha;
if(std::string("RGB ") == head)
{
alpha = false;
}
else if(std::string("RGBA") == head)
{
alpha = true;
}
else
{
std::string message("Unrecognized texture format: ");
message += head;
Error(message.c_str());
return fail;
};
GLuint width;
GLuint height;
file.read((char *) &width, sizeof(int));
file.read((char *) &height, sizeof(int));
GLuint bpp = alpha ? 4 : 3;
GLuint size = width * height * bpp;
GLubyte* data = new GLubyte[size];
file.read(data, size);
bool hash = (fileName.find('#') != std::string::npos);
GLuint id = CreateTexture(data,(alpha?GL_RGBA:GL_RGB),width,height,alpha,hash);
delete[] data;
return std::make_pair(id, alpha);
};
TTexturesManager::AlphaValue TTexturesManager::LoadDDS(std::string fileName,int filter)
{
AlphaValue fail(0, false);
std::ifstream file(fileName.c_str(), ios::binary);
char filecode[5];
file.read(filecode, 4);
filecode[4] = 0;
if(std::string("DDS ") != filecode)
{
file.close();
return fail;
};
DDSURFACEDESC2 ddsd;
file.read((char*) &ddsd, sizeof(ddsd));
DDS_IMAGE_DATA data;
//
// This .dds loader supports the loading of compressed formats DXT1, DXT3
// and DXT5.
//
GLuint factor;
switch( ddsd.ddpfPixelFormat.dwFourCC )
{
case FOURCC_DXT1:
// DXT1's compression ratio is 8:1
data.format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
factor = 2;
break;
case FOURCC_DXT3:
// DXT3's compression ratio is 4:1
data.format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
factor = 4;
break;
case FOURCC_DXT5:
// DXT5's compression ratio is 4:1
data.format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
factor = 4;
break;
default:
file.close();
return fail;
}
GLuint bufferSize = (ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * factor : ddsd.dwLinearSize);
data.pixels = new GLubyte[bufferSize];
file.read((char*)data.pixels,bufferSize);
file.close();
data.width = ddsd.dwWidth;
data.height = ddsd.dwHeight;
data.numMipMaps = ddsd.dwMipMapCount;
{//sprawdzenie prawid³owoœci rozmiarów
int i,j;
for (i=data.width,j=0;i;i>>=1) if (i&1) ++j;
if (j==1)
for (i=data.height,j=0;i;i>>=1) if (i&1) ++j;
if (j!=1) WriteLog("Bad texture: "+AnsiString(fileName.c_str())+" is "+AnsiString(data.width)+"×"+AnsiString(data.height));
}
if (ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1)
data.components = 3;
else
data.components = 4;
data.blockSize = (data.format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 8 : 16);
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
if (filter>=0)
SetFiltering(filter); //cyfra po % w nazwie
else
//SetFiltering(bHasAlpha&&bDollar,bHash); //znaki #, $ i kana³ alfa w nazwie
SetFiltering(data.components==4,fileName.find('#')!=std::string::npos);
GLuint offset = 0;
int firstMipMap = 0;
while ((data.width>Global::iMaxTextureSize)||(data.height>Global::iMaxTextureSize))
{//pomijanie zbyt du¿ych mipmap, jeœli wymagane jest ograniczenie rozmiaru
offset+=((data.width+3)/4)*((data.height+3)/4)*data.blockSize;
data.width/=2;
data.height/=2;
firstMipMap++;
};
for (int i=0;i<data.numMipMaps-firstMipMap;i++)
{//wczytanie kolejnych poziomów mipmap
if (!data.width) data.width=1;
if (!data.height) data.height=1;
GLuint size=((data.width+3)/4)*((data.height+3)/4)*data.blockSize;
if (Global::bDecompressDDS)
{//programowa dekompresja DDS
//if (i==1) //should be i==0 but then problem with "glBindTexture()"
{GLuint decomp_size=data.width*data.height*4;
GLubyte* output=new GLubyte[decomp_size];
DecompressDXT(data,data.pixels+offset,output);
glTexImage2D(GL_TEXTURE_2D,i,GL_RGBA,data.width,data.height,0,GL_RGBA,GL_UNSIGNED_BYTE,output);
delete[] output;
}
}
else //przetwarzanie DDS przez OpenGL (istnieje odpowiednie rozszerzenie)
glCompressedTexImage2D(GL_TEXTURE_2D,i,data.format,data.width,data.height,0,size,data.pixels+offset);
offset+=size;
// Half the image size for the next mip-map level...
data.width/=2;
data.height/=2;
};
delete[] data.pixels;
return std::make_pair(id, data.components == 4);
};
void TTexturesManager::SetFiltering(int filter)
{
if (filter<4) //rozmycie przy powiêkszeniu
{//brak rozmycia z bliska - tych jest 4: 0..3, aby nie by³o przeskoku
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
filter+=4;
}
else
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
switch (filter) //rozmycie przy oddaleniu
{case 4: //najbli¿szy z tekstury
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); break;
case 5: //œrednia z tekstury
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); break;
case 6: //najbli¿szy z mipmapy
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST); break;
case 7: //œrednia z mipmapy
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); break;
case 8: //najbli¿szy z dwóch mipmap
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_LINEAR); break;
case 9: //œrednia z dwóch mipmap
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); break;
}
};
void TTexturesManager::SetFiltering(bool alpha, bool hash)
{
if ( alpha || hash )
{
if (alpha) // przezroczystosc: nie wlaczac mipmapingu
{
if (hash) // #: calkowity brak filtracji - pikseloza
{
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else
{
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
}
else // filtruj ale bez dalekich mipmap - robi artefakty
{
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
}
else // $: filtruj wszystko - brzydko siê zlewa
{
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
};
///////////////////////////////////////////////////////////////////////////////
GLuint TTexturesManager::CreateTexture(char* buff,GLint bpp,int width,int height,bool bHasAlpha,bool bHash,bool bDollar,int filter)
{//Ra: u¿ywane tylko dla TGA i TEX
//Ra: dodana obs³uga GL_BGR oraz GL_BGRA dla TGA - szybciej siê wczytuje
GLuint ID;
glGenTextures(1,&ID);
glBindTexture(GL_TEXTURE_2D,ID);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
if (filter>=0)
SetFiltering(filter); //cyfra po % w nazwie
else
SetFiltering(bHasAlpha&&bDollar,bHash); //znaki #, $ i kana³ alfa w nazwie
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
glPixelStorei(GL_UNPACK_SKIP_ROWS,0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS,0);
if (bHasAlpha || bHash || (filter==0))
glTexImage2D(GL_TEXTURE_2D,0,(bHasAlpha?GL_RGBA:GL_RGB),width,height,0,bpp,GL_UNSIGNED_BYTE,buff);
else
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGB,width,height,bpp,GL_UNSIGNED_BYTE,buff);
return ID;
}
void TTexturesManager::Free()
{//usuniêcie wszyskich tekstur (bez usuwania struktury)
for (Names::iterator iter=_names.begin();iter!=_names.end();iter++)
glDeleteTextures(1,&(iter->second));
}
std::string TTexturesManager::GetName(GLuint id)
{//pobranie nazwy tekstury
for (Names::iterator iter=_names.begin();iter!=_names.end();iter++)
if (iter->second==id)
return iter->first;
return "";
};
#pragma package(smart_init)

58
Texture.h Normal file
View File

@@ -0,0 +1,58 @@
//---------------------------------------------------------------------------
#ifndef TextureH
#define TextureH
#include <map>
#include <string>
#include "opengl/glew.h"
#include "usefull.h"
/*
//Ra: miejsce umieszczenia tego jest deczko bezsensowne
void __fastcall glDebug()
{//logowanie b³êdów OpenGL
GLenum err;
if (Global::iErorrCounter==326) //tu wpisz o 1 mniej niz wartoœæ, przy której siê wy³o¿y³o
Global::iErorrCounter=Global::iErorrCounter+0; //do zastawiania pu³apki przed b³êdnym kodem
while ((err=glGetError())!=GL_NO_ERROR) //dalej jest pu³apka po wykonaniu b³êdnego kodu
WriteLog("OpenGL error found: "+AnsiString(err)+", step:"+AnsiString(Global::iErorrCounter));
++Global::iErorrCounter;
};
*/
class TTexturesManager
{
public:
static void Init();
static void Free();
static GLuint GetTextureID(char* dir,char* where,std::string name,int filter=-1);
static bool GetAlpha(GLuint ID); //McZapkie-141203: czy tekstura ma polprzeroczystosc
static std::string GetName(GLuint id);
private:
typedef std::pair<GLuint, bool> AlphaValue;
typedef std::map<std::string, GLuint> Names;
typedef std::map<GLuint, bool> Alphas;
static Names::iterator LoadFromFile(std::string name,int filter=-1);
static AlphaValue LoadBMP(std::string fileName);
static AlphaValue LoadTEX(std::string fileName);
static AlphaValue LoadTGA(std::string fileName,int filter=-1);
static AlphaValue LoadDDS(std::string fileName,int filter=-1);
static void SetFiltering(int filter);
static void SetFiltering(bool alpha, bool hash);
static GLuint CreateTexture(char *buff,GLint bpp,int width,int height,bool bHasAlpha,bool bHash,bool bDollar=true,int filter=-1);
static Names _names;
static Alphas _alphas;
// std::list<TTexture> Textures;
};
//---------------------------------------------------------------------------
#endif

299
TextureDDS.cpp Normal file
View File

@@ -0,0 +1,299 @@
#include "TextureDDS.h"
void DxtcReadColors(const GLubyte* Data, Color8888* result)
{
GLubyte r0, g0, b0, r1, g1, b1;
b0 = Data[0] & 0x1F;
g0 = ((Data[0] & 0xE0) >> 5) | ((Data[1] & 0x7) << 3);
r0 = (Data[1] & 0xF8) >> 3;
b1 = Data[2] & 0x1F;
g1 = ((Data[2] & 0xE0) >> 5) | ((Data[3] & 0x7) << 3);
r1 = (Data[3] & 0xF8) >> 3;
result[0].r = r0 << 3 | r0 >> 2;
result[0].g = g0 << 2 | g0 >> 3;
result[0].b = b0 << 3 | b0 >> 2;
result[1].r = r1 << 3 | r1 >> 2;
result[1].g = g1 << 2 | g1 >> 3;
result[1].b = b1 << 3 | b1 >> 2;
};
void DxtcReadColor(GLushort Data, Color8888* Out)
{
GLubyte r, g, b;
b = Data & 0x1f;
g = (Data & 0x7E0) >> 5;
r = (Data & 0xF800) >> 11;
Out->r = r << 3 | r >> 2;
Out->g = g << 2 | g >> 3;
Out->b = b << 3 | r >> 2;
};
void DecompressDXT1(DDS_IMAGE_DATA lImage, const GLubyte *lCompData, GLubyte *Data)
{
GLint x, y, i, j, k;
GLuint Select;
const GLubyte *Temp;
Color8888 colours[4], *col;
GLushort color_0, color_1;
GLuint bitmask, Offset;
Temp = lCompData;
colours[0].a = 0xFF;
colours[1].a = 0xFF;
colours[2].a = 0xFF;
for (y = 0; y < lImage.height; y += 4) {
for (x = 0; x < lImage.width; x += 4) {
color_0 = *((const GLushort*)Temp);
color_1 = *((const GLushort*)(Temp + 2));
DxtcReadColor(color_0, colours);
DxtcReadColor(color_1, colours + 1);
bitmask = ((const GLuint*)Temp)[1];
Temp += 8;
if (color_0 > color_1) {
// Four-color block: derive the other two colors.
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
// These 2-bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
colours[3].a = 0xFF;
}
else
{
// Three-color block: derive the other color.
// 00 = color_0, 01 = color_1, 10 = color_2,
// 11 = transparent.
// These 2-bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
colours[2].b = (colours[0].b + colours[1].b) / 2;
colours[2].g = (colours[0].g + colours[1].g) / 2;
colours[2].r = (colours[0].r + colours[1].r) / 2;
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
colours[3].a = 0x00;
}
for (j = 0, k = 0; j < 4; j++) {
for (i = 0; i < 4; i++, k++) {
Select = (bitmask & (0x03 << k*2)) >> k*2;
col = &colours[Select];
if (((x + i) < lImage.width) && ((y + j) < lImage.height)) {
Offset = (y + j) * lImage.width * lImage.components + (x + i) * lImage.components;
Data[Offset + 0] = col->r;
Data[Offset + 1] = col->g;
Data[Offset + 2] = col->b;
Data[Offset + 3] = col->a;
}
}
}
}
}
}
void DecompressDXT3(DDS_IMAGE_DATA lImage, const GLubyte *lCompData, GLubyte *Data)
{
const GLubyte* Temp = lCompData;
Color8888 colours[4], *col;
GLuint bitmask, Offset;
const GLubyte* alpha;
for (GLint y = 0; y < lImage.height; y += 4) {
for (GLint x = 0; x < lImage.width; x += 4) {
alpha = Temp;
Temp += 8;
DxtcReadColors(Temp, colours);
bitmask = ((GLuint*)Temp)[1];
Temp += 8;
// Four-color block: derive the other two colors.
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
// These 2-bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
GLuint k = 0;
for (GLint j = 0; j < 4; j++) {
for (GLint i = 0; i < 4; i++, k++) {
GLuint Select = (bitmask & (0x03 << k*2)) >> k*2;
col = &colours[Select];
if (((x + i) < lImage.width) && ((y + j) < lImage.height)) {
Offset = (y + j) * lImage.width * lImage.components + (x + i) * lImage.components;
Data[Offset + 0] = col->r;
Data[Offset + 1] = col->g;
Data[Offset + 2] = col->b;
}
}
}
for (GLint j = 0; j < 4; j++) {
GLushort word = alpha[2*j] + 256*alpha[2*j+1];
for (GLint i = 0; i < 4; i++) {
if (((x + i) < lImage.width) && ((y + j) < lImage.height)) {
Offset = (y + j) * lImage.width * lImage.components + (x + i) * lImage.components + 3;
Data[Offset] = word & 0x0F;
Data[Offset] = Data[Offset] | (Data[Offset] << 4);
}
word >>= 4;
}
}
}
}
}
void DecompressDXT5(DDS_IMAGE_DATA lImage, const GLubyte *lCompData, GLubyte *Data)
{
GLint x, y, z, i, j, k;
GLuint Select;
const GLubyte *Temp; //, r0, g0, b0, r1, g1, b1;
Color8888 colours[4], *col;
GLuint bitmask, Offset;
GLubyte alphas[8];
GLuint bits;
Temp = lCompData;
for (y = 0; y < lImage.height; y += 4) {
for (x = 0; x < lImage.width; x += 4) {
if (y >= lImage.height || x >= lImage.width)
break;
alphas[0] = Temp[0];
alphas[1] = Temp[1];
const GLubyte* alphamask = Temp + 2;
Temp += 8;
DxtcReadColors(Temp, colours);
bitmask = ((const GLuint*)Temp)[1];
Temp += 8;
// Four-color block: derive the other two colors.
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
// These 2-bit codes correspond to the 2-bit fields
// stored in the 64-bit block.
colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
k = 0;
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++, k++) {
Select = (bitmask & (0x03 << k*2)) >> k*2;
col = &colours[Select];
// only put pixels out < width or height
if (((x + i) < lImage.width) && ((y + j) < lImage.height)) {
Offset = (y + j) * lImage.width * lImage.components + (x + i) * lImage.components;
Data[Offset + 0] = col->r;
Data[Offset + 1] = col->g;
Data[Offset + 2] = col->b;
}
}
}
// 8-alpha or 6-alpha block?
if (alphas[0] > alphas[1]) {
// 8-alpha block: derive the other six alphas.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7; // bit code 010
alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7; // bit code 011
alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7; // bit code 100
alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7; // bit code 101
alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7; // bit code 110
alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7; // bit code 111
}
else {
// 6-alpha block.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5; // Bit code 010
alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5; // Bit code 011
alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5; // Bit code 100
alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5; // Bit code 101
alphas[6] = 0x00; // Bit code 110
alphas[7] = 0xFF; // Bit code 111
}
// Note: Have to separate the next two loops,
// it operates on a 6-byte system.
// First three bytes
//bits = *((ILint*)alphamask);
bits = (alphamask[0]) | (alphamask[1] << 8) | (alphamask[2] << 16);
for (j = 0; j < 2; j++) {
for (i = 0; i < 4; i++) {
// only put pixels out < width or height
if (((x + i) < lImage.width) && ((y + j) < lImage.height)) {
Offset = (y + j) * lImage.width * lImage.components + (x + i) * lImage.components + 3;
Data[Offset] = alphas[bits & 0x07];
}
bits >>= 3;
}
}
// Last three bytes
//bits = *((ILint*)&alphamask[3]);
bits = (alphamask[3]) | (alphamask[4] << 8) | (alphamask[5] << 16);
for (j = 2; j < 4; j++) {
for (i = 0; i < 4; i++) {
// only put pixels out < width or height
if (((x + i) < lImage.width) && ((y + j) < lImage.height)) {
Offset = (y + j) * lImage.width * lImage.components + (x + i) * lImage.components + 3;
Data[Offset] = alphas[bits & 0x07];
}
bits >>= 3;
}
}
}
}
}
void DecompressDXT(DDS_IMAGE_DATA lImage, const GLubyte *lCompData, GLubyte *Data)
{
switch(lImage.format)
{
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
DecompressDXT1(lImage, lCompData, Data);
break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
DecompressDXT3(lImage, lCompData, Data);
break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
DecompressDXT5(lImage, lCompData, Data);
break;
};
}

30
TextureDDS.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef TEXTURE_DDS_H
#define TEXTURE_DDS_H 1
#include "opengl/glew.h"
#pragma hdrstop
struct Color8888
{
GLubyte r; // change the order of names to change the
GLubyte g; // order of the output ARGB or BGRA, etc...
GLubyte b; // Last one is MSB, 1st is LSB.
GLubyte a;
};
struct DDS_IMAGE_DATA
{
GLsizei width;
GLsizei height;
GLint components;
GLenum format;
GLuint blockSize;
int numMipMaps;
GLubyte *pixels;
};
void DecompressDXT(DDS_IMAGE_DATA lImage, const GLubyte *lCompData, GLubyte *Data);
#endif

119
Timer.cpp Normal file
View File

@@ -0,0 +1,119 @@
//---------------------------------------------------------------------------
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Timer.h"
#include "Globals.h"
namespace Timer {
double DeltaTime,DeltaRenderTime;
double fFPS =0.0f;
double fLastTime =0.0f;
DWORD dwFrames =0L;
double fSimulationTime=0;
double fSoundTimer=0;
double fSinceStart=0;
double __fastcall GetTime()
{
return fSimulationTime;
}
double __fastcall GetDeltaTime()
{//czas symulacji (stoi gdy pauza)
return DeltaTime;
}
double __fastcall GetDeltaRenderTime()
{//czas renderowania (do poruszania siê)
return DeltaRenderTime;
}
double __fastcall GetfSinceStart()
{
return fSinceStart;
}
void __fastcall SetDeltaTime(double t)
{
DeltaTime= t;
}
double __fastcall GetSimulationTime()
{
return fSimulationTime;
}
void __fastcall SetSimulationTime(double t)
{
fSimulationTime=t;
}
bool __fastcall GetSoundTimer()
{//Ra: byæ mo¿e, by dŸwiêki nie modyfikowa³y siê zbyt czêsto, po 0.1s zeruje siê ten licznik
return (fSoundTimer==0.0f);
}
double __fastcall GetFPS()
{
return fFPS;
}
void __fastcall ResetTimers()
{
//double CurrentTime=
GetTickCount();
DeltaTime=0.1;
DeltaRenderTime=0;
fSoundTimer=0;
};
LONGLONG fr,count,oldCount;
//LARGE_INTEGER fr,count;
void __fastcall UpdateTimers(bool pause)
{
QueryPerformanceFrequency((LARGE_INTEGER*)&fr);
QueryPerformanceCounter((LARGE_INTEGER*)&count);
DeltaRenderTime=double(count-oldCount)/double(fr);
if (!pause)
{DeltaTime=Global::fTimeSpeed*DeltaRenderTime;
fSoundTimer+=DeltaTime;
if (fSoundTimer>0.1) fSoundTimer=0;
/*
double CurrentTime= double(count)/double(fr);//GetTickCount();
DeltaTime= (CurrentTime-OldTime);
OldTime= CurrentTime;
*/
if (DeltaTime>1) DeltaTime=1;
}
else
DeltaTime=0; //wszystko stoi, bo czas nie p³ynie
oldCount=count;
// Keep track of the time lapse and frame count
double fTime=GetTickCount()*0.001f; // Get current time in seconds
++dwFrames; //licznik ramek
//update the frame rate once per second
if (fTime-fLastTime>1.0f)
{
fFPS =dwFrames/(fTime-fLastTime);
fLastTime=fTime;
dwFrames =0L;
}
fSimulationTime+=DeltaTime;
};
};
//---------------------------------------------------------------------------
#pragma package(smart_init)

33
Timer.h Normal file
View File

@@ -0,0 +1,33 @@
//---------------------------------------------------------------------------
#ifndef TimerH
#define TimerH
namespace Timer {
double __fastcall GetTime();
double __fastcall GetDeltaTime();
double __fastcall GetDeltaRenderTime();
double __fastcall GetfSinceStart();
void __fastcall SetDeltaTime(double v);
double __fastcall GetSimulationTime();
void __fastcall SetSimulationTime(double v);
bool __fastcall GetSoundTimer();
double __fastcall GetFPS();
void __fastcall ResetTimers();
void __fastcall UpdateTimers(bool pause);
};
//---------------------------------------------------------------------------
#endif

2618
Track.cpp Normal file

File diff suppressed because it is too large Load Diff

224
Track.h Normal file
View File

@@ -0,0 +1,224 @@
//---------------------------------------------------------------------------
#ifndef TrackH
#define TrackH
#include "Segment.h"
#include "ResourceManager.h"
#include "opengl/glew.h"
#include <system.hpp>
#include "Classes.h"
class TEvent;
typedef enum { tt_Unknown, tt_Normal, tt_Switch, tt_Table, tt_Cross, tt_Tributary } TTrackType;
//McZapkie-100502
typedef enum {e_unknown=-1, e_flat=0, e_mountains, e_canyon, e_tunnel, e_bridge, e_bank} TEnvironmentType;
//Ra: opracować alternatywny system cieni/świateł z definiowaniem koloru oświetlenia w halach
class TTrack;
class TGroundNode;
class TSubRect;
class TTraction;
class TSwitchExtension
{//dodatkowe dane do toru, który jest zwrotnicą
public:
__fastcall TSwitchExtension(TTrack *owner,int what);
__fastcall ~TSwitchExtension();
TSegment *Segments[6]; //dwa tory od punktu 1, pozostałe dwa od 2? Ra 140101: 6 połączeń dla skrzyżowań
//TTrack *trNear[4]; //tory dołączone do punktów 1, 2, 3 i 4
//dotychczasowe [2]+[2] wskaźniki zamienić na nowe [4]
TTrack *pNexts[2]; //tory dołączone do punktów 2 i 4
TTrack *pPrevs[2]; //tory dołączone do punktów 1 i 3
int iNextDirection[2]; //to też z [2]+[2] przerobić na [4]
int iPrevDirection[2];
int CurrentIndex; //dla zwrotnicy
double fOffset,fDesiredOffset; //aktualne i docelowe położenie napędu iglic
double fOffsetSpeed; //prędkość liniowa ruchu iglic
double fOffsetDelay; //opóźnienie ruchu drugiej iglicy względem pierwszej
union
{
struct
{//zmienne potrzebne tylko dla zwrotnicy
double fOffset1,fOffset2; //przesunięcia iglic - 0=na wprost
bool RightSwitch; //czy zwrotnica w prawo
};
struct
{//zmienne potrzebne tylko dla obrotnicy/przesuwnicy
TGroundNode *pMyNode; //dla obrotnicy do wtórnego podłączania torów
//TAnimContainer *pAnim; //animator modelu dla obrotnicy
TAnimModel *pModel; //na razie model
};
struct
{//zmienne dla skrzyżowania
vector3 *vPoints; //tablica wierzchołków nawierzchni, generowana przez pobocze
int iPoints; //liczba faktycznie użytych wierzchołków nawierzchni
bool bPoints; //czy utworzone?
int iRoads; //ile dróg się spotyka?
};
};
bool bMovement; //czy w trakcie animacji
int iLeftVBO,iRightVBO; //indeksy iglic w VBO
TSubRect *pOwner; //sektor, któremu trzeba zgłosić animację
TTrack *pNextAnim; //następny tor do animowania
TEvent *evPlus,*evMinus; //zdarzenia sygnalizacji rozprucia
float fVelocity; //maksymalne ograniczenie prędkości (ustawianej eventem)
vector3 vTrans; //docelowa translacja przesuwnicy
private:
};
const int iMaxNumDynamics=40; //McZapkie-100303
class TIsolated
{//obiekt zbierający zajętości z kilku odcinków
int iAxles; //ilość osi na odcinkach obsługiwanych przez obiekt
TIsolated *pNext; //odcinki izolowane są trzymane w postaci listy jednikierunkowej
static TIsolated *pRoot; //początek listy
public:
AnsiString asName; //nazwa obiektu, baza do nazw eventów
TEvent *evBusy; //zdarzenie wyzwalane po zajęciu grupy
TEvent *evFree; //zdarzenie wyzwalane po całkowitym zwolnieniu zajętości grupy
TMemCell *pMemCell; //automatyczna komórka pamięci, która współpracuje z odcinkiem izolowanym
__fastcall TIsolated();
__fastcall TIsolated(const AnsiString &n,TIsolated *i);
__fastcall ~TIsolated();
static TIsolated* __fastcall Find(const AnsiString &n); //znalezienie obiektu albo utworzenie nowego
void __fastcall Modify(int i,TDynamicObject *o); //dodanie lub odjęcie osi
bool __fastcall Busy() { return (iAxles>0); };
static TIsolated* __fastcall Root() { return (pRoot); };
TIsolated* __fastcall Next() { return (pNext); };
};
class TTrack : public Resource
{//trajektoria ruchu - opakowanie
private:
TSwitchExtension *SwitchExtension; //dodatkowe dane do toru, który jest zwrotnicą
TSegment *Segment;
TTrack *trNext; //odcinek od strony punktu 2 - to powinno być w segmencie
TTrack *trPrev; //odcinek od strony punktu 1
//McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
GLuint TextureID1; //tekstura szyn albo nawierzchni
GLuint TextureID2; //tekstura automatycznej podsypki albo pobocza
float fTexLength; //długość powtarzania tekstury w metrach
float fTexRatio1; //proporcja rozmiarów tekstury dla nawierzchni drogi
float fTexRatio2; //proporcja rozmiarów tekstury dla chodnika
float fTexHeight1; //wysokość brzegu względem trajektorii
float fTexWidth; //szerokość boku
float fTexSlope;
double fRadiusTable[2]; //dwa promienie, drugi dla zwrotnicy
int iTrapezoid; //0-standard, 1-przechyłka, 2-trapez, 3-oba
GLuint DisplayListID;
TIsolated *pIsolated; //obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
TGroundNode *pMyNode; //Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
public:
int iNumDynamics;
TDynamicObject *Dynamics[iMaxNumDynamics];
int iEvents; //Ra: flaga informująca o obecności eventów
TEvent *evEventall0; //McZapkie-140302: wyzwalany gdy pojazd stoi
TEvent *evEventall1;
TEvent *evEventall2;
TEvent *evEvent0; //McZapkie-280503: wyzwalany tylko gdy headdriver
TEvent *evEvent1;
TEvent *evEvent2;
AnsiString asEventall0Name; //nazwy eventów
AnsiString asEventall1Name;
AnsiString asEventall2Name;
AnsiString asEvent0Name;
AnsiString asEvent1Name;
AnsiString asEvent2Name;
int iNextDirection; //0:Point1, 1:Point2, 3:do odchylonego na zwrotnicy
int iPrevDirection;
TTrackType eType;
int iCategoryFlag; //0x100 - usuwanie pojazów
float fTrackWidth; //szerokość w punkcie 1
float fTrackWidth2; //szerokość w punkcie 2 (głównie drogi i rzeki)
float fFriction; //współczynnik tarcia
float fSoundDistance;
int iQualityFlag;
int iDamageFlag;
TEnvironmentType eEnvironment; //dźwięk i oświetlenie
bool bVisible; //czy rysowany
int iAction; //czy modyfikowany eventami (specjalna obsługa przy skanowaniu)
float fOverhead; //informacja o stanie sieci: 0-jazda bezprądowa, >0-z opuszczonym i ograniczeniem prędkości
private:
double fVelocity; //prędkość dla AI (powyżej rośnie prawdopowobieństwo wykolejenia)
public:
//McZapkie-100502:
double fTrackLength; //długość z wpisu, nigdzie nie używana
double fRadius; //promień, dla zwrotnicy kopiowany z tabeli
bool ScannedFlag; //McZapkie: do zaznaczania kolorem torów skanowanych przez AI
TTraction *hvOverhead; //drut zasilający do szybkiego znalezienia (nie używany)
TGroundNode *nFouling[2]; //współrzędne ukresu albo oporu kozła
TTrack *trColides; //tor kolizyjny, na którym trzeba sprawdzać pojazdy pod kątem zderzenia
__fastcall TTrack(TGroundNode *g);
__fastcall ~TTrack();
void __fastcall Init();
static TTrack* __fastcall Create400m(int what,double dx);
TTrack* __fastcall NullCreate(int dir);
inline bool __fastcall IsEmpty() { return (iNumDynamics<=0); };
void __fastcall ConnectPrevPrev(TTrack *pNewPrev,int typ);
void __fastcall ConnectPrevNext(TTrack *pNewPrev,int typ);
void __fastcall ConnectNextPrev(TTrack *pNewNext,int typ);
void __fastcall ConnectNextNext(TTrack *pNewNext,int typ);
inline double __fastcall Length() { return Segment->GetLength(); };
inline TSegment* __fastcall CurrentSegment() { return Segment; };
inline TTrack* __fastcall CurrentNext() {return (trNext);};
inline TTrack* __fastcall CurrentPrev() {return (trPrev);};
TTrack* __fastcall Neightbour(int s,double &d);
bool __fastcall SetConnections(int i);
bool __fastcall Switch(int i,double t=-1.0,double d=-1.0);
bool __fastcall SwitchForced(int i,TDynamicObject *o);
int __fastcall CrossSegment(int from,int into);
inline int __fastcall GetSwitchState() { return (SwitchExtension?SwitchExtension->CurrentIndex:-1); };
void __fastcall Load(cParser *parser, vector3 pOrigin,AnsiString name);
bool __fastcall AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
bool __fastcall AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
bool __fastcall AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
bool __fastcall CheckDynamicObject(TDynamicObject *Dynamic);
bool __fastcall AddDynamicObject(TDynamicObject *Dynamic);
bool __fastcall RemoveDynamicObject(TDynamicObject *Dynamic);
void __fastcall MoveMe(vector3 pPosition);
void Release();
void __fastcall Compile(GLuint tex=0);
void __fastcall Render(); //renderowanie z Display Lists
int __fastcall RaArrayPrepare(); //zliczanie rozmiaru dla VBO sektroa
void __fastcall RaArrayFill(CVertNormTex *Vert,const CVertNormTex *Start); //wypełnianie VBO
void __fastcall RaRenderVBO(int iPtr); //renderowanie z VBO sektora
void __fastcall RenderDyn(); //renderowanie nieprzezroczystych pojazdów (oba tryby)
void __fastcall RenderDynAlpha(); //renderowanie przezroczystych pojazdów (oba tryby)
void __fastcall RenderDynSounds(); //odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
void __fastcall RaOwnerSet(TSubRect *o)
{if (SwitchExtension) SwitchExtension->pOwner=o;};
bool __fastcall InMovement(); //czy w trakcie animacji?
void __fastcall RaAssign(TGroundNode *gn,TAnimContainer *ac);
void __fastcall RaAssign(TGroundNode *gn,TAnimModel *am,TEvent *done,TEvent *joined);
void __fastcall RaAnimListAdd(TTrack *t);
TTrack* __fastcall RaAnimate();
void __fastcall RadioStop();
void __fastcall AxleCounter(int i,TDynamicObject *o)
{if (pIsolated) pIsolated->Modify(i,o);}; //dodanie lub odjęcie osi
AnsiString __fastcall IsolatedName();
bool __fastcall IsolatedEventsAssign(TEvent *busy,TEvent *free);
double __fastcall WidthTotal();
GLuint TextureGet(int i) {return i?TextureID1:TextureID2;};
bool __fastcall IsGroupable();
int __fastcall TestPoint(vector3 *Point);
void __fastcall MovedUp1(double dh);
AnsiString __fastcall NameGet();
void __fastcall VelocitySet(float v);
float __fastcall VelocityGet();
void __fastcall ConnectionsLog();
private:
void __fastcall EnvironmentSet();
void __fastcall EnvironmentReset();
};
//---------------------------------------------------------------------------
#endif

624
Traction.cpp Normal file
View File

@@ -0,0 +1,624 @@
//---------------------------------------------------------------------------
/*
MaSzyna EU07 locomotive simulator
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
*/
#include "system.hpp"
#include "classes.hpp"
#pragma hdrstop
#include "Traction.h"
#include "mctools.hpp"
#include "Globals.h"
#include "Usefull.h"
#include "TractionPower.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
/*
=== Koncepcja dwustronnego zasilania sekcji sieci trakcyjnej, Ra 2014-02 ===
0. Każde przęsło sieci może mieć wpisaną nazwę zasilacza, a także napięcie
nominalne i maksymalny prąd, które stanowią redundancję do danych zasilacza.
Rezystancja może się zmieniać, materiał i grubość drutu powinny być wspólny
dla segmentu. Podanie punktów umożliwia łączenie przęseł w listy dwukierunkowe,
co usprawnia wyszukiwania kolejnych przeseł podczas jazdy. Dla bieżni wspólnej
powinna być podana nazwa innego przęsła w parametrze "parallel". Wskaźniki
na przęsła bieżni wspólnej mają być układane w jednokierunkowy pierścień.
1. Problemem jest ustalenie topologii sekcji dla linii dwutorowych. Nad każdym
torem powinna znajdować się oddzielna sekcja sieci, aby mogła zostać odłączona
w przypadku zwarcia. Sekcje nad równoległymi torami są również łączone
równolegle przez kabiny sekcyjne, co zmniejsza płynące prądy i spadki napięć.
2. Drugim zagadnieniem jest zasilanie sekcji jednocześnie z dwóch stron, czyli
sekcja musi mieć swoją nazwę oraz wskazanie dwóch zasilaczy ze wskazaniem
geograficznym ich położenia. Dodatkową trudnością jest brak połączenia
pomiędzy segmentami naprężania. Podsumowując, każdy segment naprężania powinien
mieć przypisanie do sekcji zasilania, a dodatkowo skrajne segmenty powinny
wskazywać dwa różne zasilacze.
3. Zasilaczem sieci może być podstacja, która w wersji 3kV powinna generować
pod obciążeniem napięcie maksymalne rzędu 3600V, a spadek napięcia następuje
na jej rezystancji wewnętrznej oraz na przewodach trakcyjnych. Zasilaczem może
być również kabina sekcyjna, która jest zasilana z podstacji poprzez przewody
trakcyjne.
4. Dla uproszczenia można przyjąć, że zasilanie pojazdu odbywać się będzie z
dwóch sąsiednich podstacji, pomiędzy którymi może być dowolna liczba kabin
sekcyjnych. W przypadku wyłączenia jednej z tych podstacji, zasilanie może
być pobierane z kolejnej. Łącznie należy rozważać 4 najbliższe podstacje,
przy czym do obliczeń można przyjmować 2 z nich.
5. Przęsła sieci są łączone w listę dwukierunkową, więc wystarczy nazwę
sekcji wpisać w jednym z nich, wpisanie w każdym nie przeszkadza.
Alternatywnym sposobem łączenia segmentów naprężania może być wpisywanie
nazw przęseł jako "parallel", co może być uciążliwe dla autorów scenerii.
W skrajnych przęsłach należałoby dodatkowo wpisać nazwę zasilacza, będzie
to jednocześnie wskazanie przęsła, do którego podłączone są przewody
zasilające. Konieczne jest odróżnienie nazwy sekcji od nazwy zasilacza, co
można uzyskać różnicując ich nazwy albo np. specyficznie ustawiając wartość
prądu albo napięcia przęsła.
6. Jeśli dany segment naprężania jest wspólny dla dwóch sekcji zasilania,
to jedno z przęseł musi mieć nazwę "*" (gwiazdka), co będzie oznaczało, że
ma zamontowany izolator. Dla uzyskania efektów typu łuk elektryczny, należało
by wskazać położenie izolatora i jego długość (ew. typ).
7. Również w parametrach zasilacza należało by określić, czy jest podstacją,
czy jedynie kabiną sekcyjną. Różnić się one będą fizyką działania.
8. Dla zbudowanej topologii sekcji i zasilaczy należało by zbudować dynamiczny
schemat zastępczy. Dynamika polega na wyłączaniu sekcji ze zwarciem oraz
przeciążonych podstacji. Musi być też możliwość wyłączenia sekcji albo
podstacji za pomocą eventu.
9. Dla każdej sekcji musi być tworzony obiekt, wskazujący na podstacje
zasilające na końcach, stan włączenia, zwarcia, przepięcia. Do tego obiektu
musi wskazywać każde przęsło z aktywnym zasilaniem.
z.1 z.2 z.3
-=-a---1*1---c-=---c---=-c--2*2--e---=---e-3-*-3--g-=-
-=-b---1*1---d-=---d---=-d--2*2--f---=---e-3-*-3--h-=-
nazwy sekcji (@): a,b,c,d,e,f,g,h
nazwy zasilaczy (#): 1,2,3
przęsło z izolatorem: *
przęsła bez wskazania nazwy sekcji/zasilacza: -
segment napręzania: =-x-=
segment naprężania z izolatorem: =---@---#*#---@---=
segment naprężania bez izolatora: =--------@------=
Obecnie brak nazwy sekcji nie jest akceptowany i każde przęsło musi mieć wpisaną
jawnie nazwę sekcji, ewentualnie nazwę zasilacza (zostanie zastąpiona wskazaniem
sekcji z sąsiedniego przęsła).
*/
TTraction::TTraction()
{
pPoint1=pPoint2=pPoint3=pPoint4=vector3(0,0,0);
//vFront=vector3(0,0,1);
//vUp=vector3(0,1,0);
//vLeft=vector3(1,0,0);
fHeightDifference=0;
iNumSections=0;
iLines=0;
// dwFlags= 0;
Wires=2;
// fU=fR= 0;
uiDisplayList=0;
asPowerSupplyName="";
// mdPole= NULL;
// ReplacableSkinID= 0;
hvNext[0]=hvNext[1]=NULL;
iLast=1; //że niby ostatni drut
psPowered=psPower[0]=psPower[1]=NULL; //na początku zasilanie nie podłączone
psSection=NULL; //na początku nie podłączone
hvParallel=NULL; //normalnie brak bieżni wspólnej
fResistance[0]=fResistance[1]=-1.0; //trzeba dopiero policzyć
iTries=0; //ile razy próbować podłączyć, ustawiane później
}
TTraction::~TTraction()
{
if (!Global::bUseVBO)
glDeleteLists(uiDisplayList,1);
}
void __fastcall TTraction::Optimize()
{
if (Global::bUseVBO) return;
uiDisplayList=glGenLists(1);
glNewList(uiDisplayList,GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, 0);
// glColor3ub(0,0,0); McZapkie: to do render
// glPushMatrix();
// glTranslatef(pPosition.x,pPosition.y,pPosition.z);
if (Wires!=0)
{
//Dlugosc odcinka trakcji 'Winger
double ddp=hypot(pPoint2.x-pPoint1.x,pPoint2.z-pPoint1.z);
if (Wires==2) WireOffset=0;
//Przewoz jezdny 1 'Marcin
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint1.x-(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset,pPoint1.y,pPoint1.z-(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset);
glVertex3f(pPoint2.x-(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset,pPoint2.y,pPoint2.z-(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset);
glEnd();
//Nie wiem co 'Marcin
vector3 pt1,pt2,pt3,pt4,v1,v2;
v1= pPoint4-pPoint3;
v2= pPoint2-pPoint1;
float step= 0;
if (iNumSections>0)
step= 1.0f/(float)iNumSections;
float f= step;
float mid= 0.5;
float t;
//Przewod nosny 'Marcin
if (Wires != 1)
{
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint3.x,pPoint3.y,pPoint3.z);
for (int i=0; i<iNumSections-1; i++)
{
pt3= pPoint3+v1*f;
t= (1-fabs(f-mid)*2);
if ((Wires<4)||((i!=0)&&(i!=iNumSections-2)))
glVertex3f(pt3.x,pt3.y-sqrt(t)*fHeightDifference,pt3.z);
f+= step;
}
glVertex3f(pPoint4.x,pPoint4.y,pPoint4.z);
glEnd();
}
//Drugi przewod jezdny 'Winger
if (Wires > 2)
{
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint1.x+(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset,pPoint1.y,pPoint1.z+(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset);
glVertex3f(pPoint2.x+(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset,pPoint2.y,pPoint2.z+(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset);
glEnd();
}
f= step;
if (Wires == 4)
{
glBegin(GL_LINE_STRIP);
glVertex3f(pPoint3.x,pPoint3.y-0.65f*fHeightDifference,pPoint3.z);
for (int i=0; i<iNumSections-1; i++)
{
pt3= pPoint3+v1*f;
t= (1-fabs(f-mid)*2);
glVertex3f(pt3.x,pt3.y-sqrt(t)*fHeightDifference-((i==0)||(i==iNumSections-2)?0.25f*fHeightDifference:+0.05),pt3.z);
f+= step;
}
glVertex3f(pPoint4.x,pPoint4.y-0.65f*fHeightDifference,pPoint4.z);
glEnd();
}
f= step;
//Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
if (Wires != 1)
{
glBegin(GL_LINES);
for (int i=0; i<iNumSections-1; i++)
{
float flo,flo1;
flo=(Wires==4?0.25f*fHeightDifference:0);
flo1=(Wires==4?+0.05:0);
pt3= pPoint3+v1*f;
pt4= pPoint1+v2*f;
t= (1-fabs(f-mid)*2);
if ((i%2) == 0)
{
glVertex3f(pt3.x,pt3.y-sqrt(t)*fHeightDifference-((i==0)||(i==iNumSections-2)?flo:flo1),pt3.z);
glVertex3f(pt4.x-(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset,pt4.y,pt4.z-(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset);
}
else
{
glVertex3f(pt3.x,pt3.y-sqrt(t)*fHeightDifference-((i==0)||(i==iNumSections-2)?flo:flo1),pt3.z);
glVertex3f(pt4.x+(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset,pt4.y,pt4.z+(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset);
}
if((Wires==4)&&((i==1)||(i==iNumSections-3)))
{
glVertex3f(pt3.x,pt3.y-sqrt(t)*fHeightDifference-0.05,pt3.z);
glVertex3f(pt3.x,pt3.y-sqrt(t)*fHeightDifference,pt3.z);
}
//endif;
f+= step;
}
glEnd();
}
glEndList();
}
}
/*
void __fastcall TTraction::InitCenter(vector3 Angles, vector3 pOrigin)
{
pPosition= (pPoint2+pPoint1)*0.5f;
fSquaredRadius= SquareMagnitude((pPoint2-pPoint1)*0.5f);
} */
void __fastcall TTraction::RenderDL(float mgn) //McZapkie: mgn to odleglosc od obserwatora
{
//McZapkie: ustalanie przezroczystosci i koloru linii:
if (Wires!=0 && !TestFlag(DamageFlag,128)) //rysuj jesli sa druty i nie zerwana
{
//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.2) linealpha=1.2; //zbyt grube nie są dobre
glLineWidth(linealpha);
if (linealpha>1.0) linealpha = 1.0;
//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.00000; g=0.32549; b=0.2882353; //zielona miedź
}
else
{
r=0.35098; g=0.22549; b=0.1; //czerwona miedź
}
break;
case 2:
if (TestFlag(DamageFlag,1))
{
r=0.10; g=0.10; b=0.10; //czarne Al
}
else
{
r=0.25; g=0.25; b=0.25; //srebrne Al
}
break;
//tymczasowo pokazanie zasilanych odcinków
case 4: r=0.5; g=0.5; b=1.0; break; //niebieskie z podłączonym zasilaniem
case 5: r=1.0; g=0.0; b=0.0; break; //czerwone z podłączonym zasilaniem 1
case 6: r=0.0; g=1.0; b=0.0; break; //zielone z podłączonym zasilaniem 2
case 7: r=1.0; g=1.0; b=0.0; break; //żółte z podłączonym zasilaniem z obu stron
}
if (DebugModeFlag)
if (hvParallel)
{//jeśli z bieżnią wspólną, to dodatkowo przyciemniamy
r*=0.6; g*=0.6; b*=0.6;
}
r*=Global::ambientDayLight[0]; //w zaleźności od koloru swiatła
g*=Global::ambientDayLight[1];
b*=Global::ambientDayLight[2];
if (linealpha>1.0) linealpha=1.0; //trzeba ograniczyć do <=1
glColor4f(r,g,b,linealpha);
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ą
}
}
int __fastcall 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;
}
//else iLines=0;
return iLines;
};
void __fastcall TTraction::RaArrayFill(CVertNormTex *Vert)
{//wypełnianie tablic VBO
CVertNormTex *old=Vert;
double ddp=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;
Vert->x=pPoint2.x-(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset;
Vert->y=pPoint2.y;
Vert->z=pPoint2.z-(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset;
++Vert;
//Nie wiem co 'Marcin
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)
{//lina nośna w kawałkach
Vert->x=pPoint3.x;
Vert->y=pPoint3.y;
Vert->z=pPoint3.z;
++Vert;
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;
f+=step;
}
Vert->x=pPoint4.x;
Vert->y=pPoint4.y;
Vert->z=pPoint4.z;
++Vert;
}
//Drugi przewod jezdny 'Winger
if (Wires==3)
{
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;
Vert->x=pPoint2.x+(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset;
Vert->y=pPoint2.y;
Vert->z=pPoint2.z+(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset;
++Vert;
}
f=step;
//Przewody pionowe (wieszaki) 'Marcin, poprawki na 2 przewody jezdne 'Winger
if (Wires>1)
{
for (int i=0;i<iNumSections-1;i++)
{
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;
}
else
{
Vert->x=pt4.x+(pPoint2.z/ddp-pPoint1.z/ddp)*WireOffset;
Vert->y=pt4.y;
Vert->z=pt4.z+(-pPoint2.x/ddp+pPoint1.x/ddp)*WireOffset;
}
++Vert;
f+=step;
}
}
if ((Vert-old)!=iLines)
WriteLog("!!! Wygenerowano punktów "+AnsiString(Vert-old)+", powinno być "+AnsiString(iLines));
};
void __fastcall TTraction::RenderVBO(float mgn,int iPtr)
{//renderowanie z użyciem VBO
if (Wires!=0 && !TestFlag(DamageFlag,128)) //rysuj jesli sa druty i nie zerwana
{
glBindTexture(GL_TEXTURE_2D,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.2) linealpha=1.2; //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.00000; g=0.32549; b=0.2882353; //zielona miedź
}
else
{
r=0.35098; g=0.22549; b=0.1; //czerwona miedź
}
break;
case 2:
if (TestFlag(DamageFlag,1))
{
r=0.10; g=0.10; b=0.10; //czarne Al
}
else
{
r=0.25; g=0.25; b=0.25; //srebrne Al
}
break;
//tymczasowo pokazanie zasilanych odcinków
case 4: r=0.5; g=0.5; b=1.0; break; //niebieskie z podłączonym zasilaniem
case 5: r=1.0; g=0.0; b=0.0; break; //czerwone z podłączonym zasilaniem 1
case 6: r=0.0; g=1.0; b=0.0; break; //zielone z podłączonym zasilaniem 2
case 7: r=1.0; g=1.0; b=0.0; break; //żółte z podłączonym zasilaniem z obu stron
}
r=r*Global::ambientDayLight[0]; //w zaleznosci od koloru swiatla
g=g*Global::ambientDayLight[1];
b=b*Global::ambientDayLight[2];
if (linealpha>1.0) linealpha=1.0; //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ą
}
};
int __fastcall TTraction::TestPoint(vector3 *Point)
{//sprawdzanie, czy przęsła można połączyć
if (!hvNext[0])
if (pPoint1.Equal(Point))
return 0;
if (!hvNext[1])
if (pPoint2.Equal(Point))
return 1;
return -1;
};
void __fastcall TTraction::Connect(int my,TTraction *with,int to)
{//łączenie segmentu (with) od strony (my) do jego (to)
if (my)
{//do mojego Point2
hvNext[1]=with;
iNext[1]=to;
}
else
{//do mojego Point1
hvNext[0]=with;
iNext[0]=to;
}
if (to)
{//do jego Point2
with->hvNext[1]=this;
with->iNext[1]=my;
}
else
{//do jego Point1
with->hvNext[0]=this;
with->iNext[0]=my;
}
if (hvNext[0]) //jeśli z obu stron podłączony
if (hvNext[1])
iLast=0; //to nie jest ostatnim
if (with->hvNext[0]) //temu też, bo drugi raz łączenie się nie nie wykona
if (with->hvNext[1])
with->iLast=0; //to nie jest ostatnim
};
bool __fastcall TTraction::WhereIs()
{//ustalenie przedostatnich przęseł
if (iLast) return (iLast==1); //ma już ustaloną informację o położeniu
if (hvNext[0]?hvNext[0]->iLast==1:false) //jeśli poprzedni jest ostatnim
iLast=2; //jest przedostatnim
else
if (hvNext[1]?hvNext[1]->iLast==1:false) //jeśli następny jest ostatnim
iLast=2; //jest przedostatnim
return (iLast==1); //ostatnie będą dostawać zasilanie
};
void __fastcall TTraction::Init()
{//przeliczenie parametrów
vParametric=pPoint2-pPoint1; //wektor mnożników parametru dla równania parametrycznego
};
void __fastcall TTraction::ResistanceCalc(int d,double r,TTractionPowerSource *ps)
{//(this) jest przęsłem zasilanym, o rezystancji (r), policzyć rezystancję zastępczą sąsiednich
if (d>=0)
{//podążanie we wskazanym kierunku
TTraction *t=hvNext[d],*p;
if (ps)
psPower[d^1]=ps; //podłączenie podanego
else
ps=psPower[d^1]; //zasilacz od przeciwnej strony niż idzie analiza
d=iNext[d]; //kierunek
//double r; //sumaryczna rezystancja
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
{//ustawienie zasilacza i policzenie rezystancji zastępczej
if (DebugModeFlag) //tylko podczas testów
if (t->Material!=4) //przęsła zasilającego nie modyfikować
{if (t->Material<4) t->Material=4; //tymczasowo, aby zmieniła kolor
t->Material|=d?2:1; //kolor zależny od strony, z której jest zasilanie
}
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
p=t; //zapamiętanie dotychczasowego
t=p->hvNext[d^1]; //podążanie w tę samą stronę
d=p->iNext[d^1];
//w przypadku zapętlenia sieci może się zawiesić?
}
}
else
{//podążanie w obu kierunkach, można by rekurencją, ale szkoda zasobów
r=0.5*fResistivity*Length3(vParametric); //powiedzmy, że w zasilanym przęśle jest połowa
if (fResistance[0]==0.0) ResistanceCalc(0,r); //do tyłu (w stronę Point1)
if (fResistance[1]==0.0) ResistanceCalc(1,r); //do przodu (w stronę Point2)
}
};
void __fastcall TTraction::PowerSet(TTractionPowerSource *ps)
{//podłączenie przęsła do zasilacza
if (ps->bSection)
psSection=ps; //ustalenie sekcji zasilania
else
{//ustalenie punktu zasilania (nie ma jeszcze połączeń między przęsłami)
psPowered=ps; //ustawienie bezpośredniego zasilania dla przęsła
psPower[0]=psPower[1]=ps; //a to chyba nie jest dobry pomysł, bo nawet zasilane przęsło powinno mieć wskazania na inne
fResistance[0]=fResistance[1]=0.0; //a liczy się tylko rezystancja zasilacza
}
};
double __fastcall TTraction::VoltageGet(double u,double i)
{//pobranie napięcia na przęśle po podłączeniu do niego rezystancji (res) - na razie jest to prąd
if (!psSection)
if (!psPowered)
return NominalVoltage; //jak nie ma zasilacza, to napięcie podane w przęśle
//na początek można założyć, że wszystkie podstacje mają to samo napięcie i nie płynie prąd pomiędzy nimi
//dla danego przęsła mamy 3 źródła zasilania
//1. zasilacz psPower[0] z rezystancją fResistance[0] oraz jego wewnętrzną
//2. zasilacz psPower[1] z rezystancją fResistance[1] oraz jego wewnętrzną
//3. zasilacz psPowered z jego wewnętrzną rezystancją dla przęseł zasilanych bezpośrednio
double res=(i!=0.0)?fabs(u/i):10000.0;
if (psPowered) return psPowered->CurrentGet(res)*res; //yB: dla zasilanego nie baw się w gwiazdy, tylko bierz bezpośrednio
double r0t,r1t,r0g,r1g;
double u0,u1,i0,i1;
r0t=fResistance[0]; //średni pomysł, ale lepsze niż nic
r1t=fResistance[1]; //bo nie uwzględnia spadków z innych pojazdów
if (psPower[0]&&psPower[1])
{//gdy przęsło jest zasilane z obu stron - mamy trójkąt: res, r0t, r1t
//yB: Gdy wywali podstacja, to zaczyna się robić nieciekawie - napięcie w sekcji na jednym końcu jest równe zasilaniu,
//yB: a na drugim końcu jest równe 0. Kolejna sprawa to rozróżnienie uszynienia sieci na podstacji/odłączniku (czyli
//yB: potencjał masy na sieci) od braku zasilania (czyli odłączenie źródła od sieci i brak jego wpływu na napięcie).
if ((r0t>0.0)&&(r1t>0.0))
{//rezystancje w mianowniku nie mogą być zerowe
r0g=res+r0t+(res*r0t)/r1t; //przeliczenie z trójkąta na gwiazdę
r1g=res+r1t+(res*r1t)/r0t;
//pobierane są prądy dla każdej rezystancji, a suma jest mnożona przez rezystancję pojazdu w celu uzyskania napięcia
i0=psPower[0]->CurrentGet(r0g); //oddzielnie dla sprawdzenia
i1=psPower[1]->CurrentGet(r1g);
return (i0+i1)*res;
}
else if (r0t>=0.0)
return psPower[0]->CurrentGet(res+r0t)*res;
else if (r1t>=0.0)
return psPower[1]->CurrentGet(res+r1t)*res;
else
return 0.0; //co z tym zrobić?
}
else if (psPower[0]&&(r0t>=0.0))
{//jeśli odcinek podłączony jest tylko z jednej strony
return psPower[0]->CurrentGet(res+r0t)*res;
}
else if (psPower[1]&&(r1t>=0.0))
return psPower[1]->CurrentGet(res+r1t)*res;
return 0.0; //gdy nie podłączony wcale?
};

Some files were not shown because too many files have changed in this diff Show More