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

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

This commit is contained in:
firleju
2017-09-06 09:41:35 +02:00
18 changed files with 407 additions and 284 deletions

View File

@@ -32,6 +32,59 @@ http://mozilla.org/MPL/2.0/.
#define LOGSTOPS 1 #define LOGSTOPS 1
#define LOGBACKSCAN 0 #define LOGBACKSCAN 0
#define LOGPRESS 0 #define LOGPRESS 0
// finds point of specified track nearest to specified event. returns: distance to that point from the specified end of the track
// TODO: move this to file with all generic routines, too easy to forget it's here and it may come useful
double
ProjectEventOnTrack( TEvent const *Event, TTrack const *Track, double const Direction ) {
auto const segment = Track->CurrentSegment();
auto const nearestpoint = segment->find_nearest_point( Event->PositionGet() );
return (
Direction > 0 ?
nearestpoint * segment->GetLength() : // measure from point1
( 1.0 - nearestpoint ) * segment->GetLength() ); // measure from point2
};
double GetDistanceToEvent(TTrack* track, TEvent* event, double scan_dir, double start_dist, int iter = 0, bool back = false)
{
if( track == nullptr ) { return start_dist; }
auto const segment = track->CurrentSegment();
vector3 const pos_event = event->PositionGet();
double len1, len2;
double sd = scan_dir;
double seg_len = scan_dir > 0 ? 0.0 : 1.0;
double const dzielnik = 1.0 / segment->GetLength();// rozdzielczosc mniej wiecej 1m
int krok = 0; // krok obliczeniowy do sprawdzania czy odwracamy
len2 = (pos_event - segment->FastGetPoint(seg_len)).LengthSquared();
do
{
len1 = len2;
seg_len += scan_dir > 0 ? dzielnik : -dzielnik;
len2 = (pos_event - segment->FastGetPoint(seg_len)).LengthSquared();
krok++;
} while ((len1 > len2) && (seg_len >= dzielnik && (seg_len <= (1 - dzielnik))));
//trzeba sprawdzić czy seg_len nie osiągnął skrajnych wartości, bo wtedy
// trzeba sprawdzić tor obok
if (1 == krok)
sd = -sd; // jeśli tylko jeden krok tzn, że event przy poprzednim sprawdzaym torze
if (((seg_len <= dzielnik) || (seg_len > (1 - dzielnik))) && (iter < 3))
{ // przejście na inny tor
track = track->Neightbour(int(sd), sd);
start_dist += (1 == krok) ? 0 : back ? -segment->GetLength() : segment->GetLength();
return GetDistanceToEvent(track, event, sd, start_dist, ++iter, 1 == krok ? true : false);
}
else
{ // obliczenie mojego toru
seg_len -= scan_dir > 0 ? dzielnik : -dzielnik; //trzeba wrócić do pozycji len1
seg_len = scan_dir < 0 ? 1 - seg_len : seg_len;
seg_len = back ? 1 - seg_len : seg_len; // odwracamy jeśli idzie do tyłu
start_dist -= back ? segment->GetLength() : 0;
return start_dist + (segment->GetLength() * seg_len);
}
};
/* /*
Moduł obsługujący sterowanie pojazdami (składami pociągów, samochodami). Moduł obsługujący sterowanie pojazdami (składami pociągów, samochodami).
@@ -106,43 +159,6 @@ std::string StopReasonTable[] = {
"Error", // stopError //z powodu błędu w obliczeniu drogi hamowania "Error", // stopError //z powodu błędu w obliczeniu drogi hamowania
}; };
double GetDistanceToEvent(TTrack* track, TEvent* event, double scan_dir, double start_dist, int iter = 0, bool back = false)
{
std::shared_ptr<TSegment> segment = track->CurrentSegment();
vector3 pos_event = event->PositionGet();
double len1, len2;
double sd = scan_dir;
double seg_len = scan_dir > 0 ? 0.0 : 1.0;
double dzielnik = 1.0 / segment->GetLength();// rozdzielczosc mniej wiecej 1m
int krok = 0; // krok obliczeniowy do sprawdzania czy odwracamy
len2 = (pos_event - segment->FastGetPoint(seg_len)).Length();
do
{
len1 = len2;
seg_len += scan_dir > 0 ? dzielnik : -dzielnik;
len2 = (pos_event - segment->FastGetPoint(seg_len)).Length();
krok++;
} while ((len1 > len2) && (seg_len >= dzielnik && (seg_len <= (1 - dzielnik))));
//trzeba sprawdzić czy seg_len nie osiągnął skrajnych wartości, bo wtedy
// trzeba sprawdzić tor obok
if (1 == krok)
sd = -sd; // jeśli tylko jeden krok tzn, że event przy poprzednim sprawdzaym torze
if (((seg_len <= dzielnik) || (seg_len > (1 - dzielnik))) && (iter < 3))
{ // przejście na inny tor
track = track->Neightbour(int(sd), sd);
start_dist += (1 == krok) ? 0 : back ? -segment->GetLength() : segment->GetLength();
return GetDistanceToEvent(track, event, sd, start_dist, ++iter, 1 == krok ? true : false);
}
else
{ // obliczenie mojego toru
seg_len -= scan_dir > 0 ? dzielnik : -dzielnik; //trzeba wrócić do pozycji len1
seg_len = scan_dir < 0 ? 1 - seg_len : seg_len;
seg_len = back ? 1 - seg_len : seg_len; // odwracamy jeśli idzie do tyłu
start_dist -= back ? segment->GetLength() : 0;
return start_dist + (segment->GetLength() * seg_len);
}
};
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -389,7 +405,7 @@ void TController::TableClear()
eSignSkip = nullptr; // nic nie pomijamy eSignSkip = nullptr; // nic nie pomijamy
}; };
TEvent * TController::CheckTrackEvent(double fDirection, TTrack *Track) TEvent * TController::CheckTrackEvent( TTrack *Track, double const fDirection ) const
{ // sprawdzanie eventów na podanym torze do podstawowego skanowania { // sprawdzanie eventów na podanym torze do podstawowego skanowania
TEvent *e = (fDirection > 0) ? Track->evEvent2 : Track->evEvent1; TEvent *e = (fDirection > 0) ? Track->evEvent2 : Track->evEvent1;
if (!e) if (!e)
@@ -449,7 +465,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
} }
fTrackLength -= odl_czola_od_wozka; fTrackLength -= odl_czola_od_wozka;
fCurrentDistance = -fLength - fTrackLength; // aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu fCurrentDistance = -fLength - fTrackLength; // aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu
fLastVel = pTrack->VelocityGet(); // aktualna prędkość fLastVel = -1.0; // pTrack->VelocityGet(); // aktualna prędkość // changed to -1 to recognize speed limit, if any
sSpeedTable.clear(); sSpeedTable.clear();
iLast = -1; iLast = -1;
tLast = nullptr; //żaden nie sprawdzony tLast = nullptr; //żaden nie sprawdzony
@@ -509,7 +525,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
WriteLog( "Speed table for " + OwnerName() + " tracing through track " + pTrack->NameGet() ); WriteLog( "Speed table for " + OwnerName() + " tracing through track " + pTrack->NameGet() );
} }
if( ( pEvent = CheckTrackEvent( fLastDir, pTrack ) ) != nullptr ) // jeśli jest semafor na tym torze if( ( pEvent = CheckTrackEvent( pTrack, fLastDir ) ) != nullptr ) // jeśli jest semafor na tym torze
{ // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie jest korzystne { // trzeba sprawdzić tabelkę, bo dodawanie drugi raz tego samego przystanku nie jest korzystne
if (TableNotFound(pEvent)) // jeśli nie ma if (TableNotFound(pEvent)) // jeśli nie ma
{ {
@@ -519,7 +535,16 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
WriteLog("Speed table for " + OwnerName() + " found new event, " + pEvent->asName); WriteLog("Speed table for " + OwnerName() + " found new event, " + pEvent->asName);
} }
auto &newspeedpoint = sSpeedTable[iLast]; auto &newspeedpoint = sSpeedTable[iLast];
if (newspeedpoint.Set(pEvent, GetDistanceToEvent(pTrack, pEvent, fLastDir, fCurrentDistance), OrderCurrentGet())) { /*
if( newspeedpoint.Set(
pEvent,
fCurrentDistance + ProjectEventOnTrack( pEvent, pTrack, fLastDir ),
OrderCurrentGet() ) ) {
*/
if( newspeedpoint.Set(
pEvent,
GetDistanceToEvent( pTrack, pEvent, fLastDir, fCurrentDistance ),
OrderCurrentGet() ) ) {
fDistance = newspeedpoint.fDist; // jeśli sygnał stop, to nie ma potrzeby dalej skanować fDistance = newspeedpoint.fDist; // jeśli sygnał stop, to nie ma potrzeby dalej skanować
SemNextStopIndex = iLast; SemNextStopIndex = iLast;
@@ -609,29 +634,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
if( ( tLast->VelocityGet() > 0 ) if( ( tLast->VelocityGet() > 0 )
&& ( ( tLast->VelocityGet() < pTrack->VelocityGet() ) && ( ( tLast->VelocityGet() < pTrack->VelocityGet() )
|| ( pTrack->VelocityGet() < 0 ) ) ) { || ( pTrack->VelocityGet() < 0 ) ) ) {
/*
if( ( pTrack->VelocityGet() < 0 ?
tLast->VelocityGet() > 0 :
pTrack->VelocityGet() > tLast->VelocityGet() ) ) {
// jeśli kolejny ma większą prędkość niż poprzedni, to zapamiętać poprzedni (do czasu wyjechania)
if( ( ( ( iLast != -1 )
&& ( TestFlag( sSpeedTable[ iLast ].iFlags, spEnabled | spTrack ) ) ) ?
( sSpeedTable[ iLast ].trTrack != tLast ) :
true ) ) {
// jeśli nie był dodany do tabelki
if( TableAddNew() ) {
// zapisanie toru z ograniczeniem prędkości
sSpeedTable[ iLast ].Set(
tLast, fCurrentDistance,
( fLastDir > 0 ?
pTrack->iPrevDirection :
pTrack->iNextDirection ) ?
spEnabled :
spEnabled | spReverse );
}
}
*/
if( ( iLast != -1 ) if( ( iLast != -1 )
&& ( sSpeedTable[ iLast ].trTrack == tLast ) ) { && ( sSpeedTable[ iLast ].trTrack == tLast ) ) {
// if the track is already in the table we only need to mark it as relevant // if the track is already in the table we only need to mark it as relevant
@@ -663,7 +666,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
if( TableAddNew() ) { if( TableAddNew() ) {
// zapisanie ostatniego sprawdzonego toru // zapisanie ostatniego sprawdzonego toru
sSpeedTable[iLast].Set( sSpeedTable[iLast].Set(
tLast, fCurrentDistance, tLast, fCurrentDistance - fTrackLength, // by now the current distance points to beginning of next track,
( fLastDir < 0 ? ( fLastDir < 0 ?
spEnabled | spEnd | spReverse : spEnabled | spEnd | spReverse :
spEnabled | spEnd )); spEnabled | spEnd ));
@@ -697,9 +700,10 @@ void TController::TableCheck(double fDistance)
} }
else if (iTableDirection) else if (iTableDirection)
{ // trzeba sprawdzić, czy coś się zmieniło { // trzeba sprawdzić, czy coś się zmieniło
for (auto &sp : sSpeedTable) auto const distance = MoveDistanceGet();
{ for (auto &sp : sSpeedTable) {
sp.UpdateDistance(MoveDistanceGet()); // aktualizacja odległości dla wszystkich pozycji tabeli // aktualizacja odległości dla wszystkich pozycji tabeli
sp.UpdateDistance(distance);
} }
MoveDistanceReset(); // kasowanie odległości po aktualizacji tabelki MoveDistanceReset(); // kasowanie odległości po aktualizacji tabelki
for( int i = 0; i < iLast; ++i ) for( int i = 0; i < iLast; ++i )
@@ -3665,7 +3669,7 @@ TController::UpdateSituation(double dt) {
// towards coupler 0 // towards coupler 0
if( ( mvOccupied->V * iDirection < 0.0 ) if( ( mvOccupied->V * iDirection < 0.0 )
|| ( ( rearvehicle->NextConnected != nullptr ) || ( ( rearvehicle->NextConnected != nullptr )
&& ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 1 : 0 ) ].CouplingFlag == ctrain_virtual ) ) ) { && ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 1 : 0 ) ].CouplingFlag == coupling::faux ) ) ) {
// scan behind if we're moving backward, or if we had something connected there and are moving away // scan behind if we're moving backward, or if we had something connected there and are moving away
rearvehicle->ABuScanObjects( ( rearvehicle->ABuScanObjects( (
pVehicle->DirectionGet() == rearvehicle->DirectionGet() ? pVehicle->DirectionGet() == rearvehicle->DirectionGet() ?
@@ -3683,7 +3687,7 @@ TController::UpdateSituation(double dt) {
// towards coupler 1 // towards coupler 1
if( ( mvOccupied->V * iDirection < 0.0 ) if( ( mvOccupied->V * iDirection < 0.0 )
|| ( ( rearvehicle->PrevConnected != nullptr ) || ( ( rearvehicle->PrevConnected != nullptr )
&& ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 0 : 1 ) ].CouplingFlag == ctrain_virtual ) ) ) { && ( rearvehicle->MoverParameters->Couplers[ ( rearvehicle->DirectionGet() > 0 ? 0 : 1 ) ].CouplingFlag == coupling::faux ) ) ) {
// scan behind if we're moving backward, or if we had something connected there and are moving away // scan behind if we're moving backward, or if we had something connected there and are moving away
rearvehicle->ABuScanObjects( ( rearvehicle->ABuScanObjects( (
pVehicle->DirectionGet() == rearvehicle->DirectionGet() ? pVehicle->DirectionGet() == rearvehicle->DirectionGet() ?
@@ -3699,6 +3703,8 @@ TController::UpdateSituation(double dt) {
} }
} }
// tu bedzie logika sterowania // tu bedzie logika sterowania
if (AIControllFlag) { if (AIControllFlag) {
@@ -3946,6 +3952,11 @@ TController::UpdateSituation(double dt) {
// NOTE: this will affect also multi-unit vehicles TBD: is this what we want? // NOTE: this will affect also multi-unit vehicles TBD: is this what we want?
fMinProximityDist *= 2.0; fMinProximityDist *= 2.0;
fMaxProximityDist *= 2.0; fMaxProximityDist *= 2.0;
if( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ) {
// additional safety margin for cargo consists
fMinProximityDist *= 2.0;
fMaxProximityDist *= 2.0;
}
} }
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
// margines prędkości powodujący załączenie napędu // margines prędkości powodujący załączenie napędu
@@ -4250,7 +4261,7 @@ TController::UpdateSituation(double dt) {
0 : 0 :
1 ); // sprzęg z przodu składu 1 ); // sprzęg z przodu składu
if( ( coupler->Connected ) if( ( coupler->Connected )
&& ( coupler->CouplingFlag == 0 ) ) { && ( coupler->CouplingFlag == coupling::faux ) ) {
// mamy coś z przodu podłączone sprzęgiem wirtualnym // mamy coś z przodu podłączone sprzęgiem wirtualnym
// wyliczanie optymalnego przyspieszenia do jazdy na widoczność // wyliczanie optymalnego przyspieszenia do jazdy na widoczność
ActualProximityDist = std::min( ActualProximityDist = std::min(
@@ -4555,24 +4566,16 @@ TController::UpdateSituation(double dt) {
// zapobieganie poslizgowi u nas // zapobieganie poslizgowi u nas
if (mvControlling->SlippingWheels) { if (mvControlling->SlippingWheels) {
if (!mvControlling->DecScndCtrl(2)) // bocznik na zero if( false == mvControlling->DecScndCtrl( 2 ) ) {
mvControlling->DecMainCtrl(1); // bocznik na zero
/* mvControlling->DecMainCtrl( 1 );
if (mvOccupied->BrakeCtrlPos == }
mvOccupied->BrakeCtrlPosNo) // jeśli ostatnia pozycja hamowania DecBrake(); // cofnij hamulec
//yB: ten warunek wyżej nie ma sensu
mvOccupied->DecBrakeLevel(); // to cofnij hamulec
DecBrake(); // to cofnij hamulec
else
mvControlling->AntiSlippingButton();
*/
DecBrake(); // to cofnij hamulec
mvControlling->AntiSlippingButton(); mvControlling->AntiSlippingButton();
++iDriverFailCount; ++iDriverFailCount;
mvControlling->SlippingWheels = false; // flaga już wykorzystana
} }
if (iDriverFailCount > maxdriverfails) if (iDriverFailCount > maxdriverfails) {
{
Psyche = Easyman; Psyche = Easyman;
if (iDriverFailCount > maxdriverfails * 2) if (iDriverFailCount > maxdriverfails * 2)
SetDriverPsyche(); SetDriverPsyche();

View File

@@ -369,7 +369,7 @@ private: // parametry aktualnego składu
// double Distance(vector3 &p1, vector3 &n, vector3 &p2); // double Distance(vector3 &p1, vector3 &n, vector3 &p2);
private: // Ra: metody obsługujące skanowanie toru private: // Ra: metody obsługujące skanowanie toru
TEvent *CheckTrackEvent(double fDirection, TTrack *Track); TEvent *CheckTrackEvent(TTrack *Track, double const fDirection ) const;
// bool TableCheckEvent(TEvent *e); // bool TableCheckEvent(TEvent *e);
bool TableAddNew(); bool TableAddNew();
bool TableNotFound(TEvent const *Event) const; bool TableNotFound(TEvent const *Event) const;

View File

@@ -1127,7 +1127,7 @@ void TDynamicObject::ABuCheckMyTrack()
// Ra: w poniższej funkcji jest problem ze sprzęgami // Ra: w poniższej funkcji jest problem ze sprzęgami
TDynamicObject * TDynamicObject *
TDynamicObject::ABuFindObject( int &Foundcoupler, double &Distance, TTrack *Track, int const Direction, int const Mycoupler ) TDynamicObject::ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler )
{ // Zwraca wskaźnik najbliższego obiektu znajdującego się { // Zwraca wskaźnik najbliższego obiektu znajdującego się
// na torze w określonym kierunku, ale tylko wtedy, kiedy // na torze w określonym kierunku, ale tylko wtedy, kiedy
// obiekty mogą się zderzyć, tzn. nie mijają się. // obiekty mogą się zderzyć, tzn. nie mijają się.
@@ -1169,7 +1169,15 @@ TDynamicObject::ABuFindObject( int &Foundcoupler, double &Distance, TTrack *Trac
for( auto dynamic : Track->Dynamics ) { for( auto dynamic : Track->Dynamics ) {
if( dynamic == this ) { continue; } // szukający się nie liczy if( dynamic == this ) { continue; } // szukający się nie liczy
/*
if( ( ( dynamic == PrevConnected ) && ( MoverParameters->Couplers[ TMoverParameters::side::front ].CouplingFlag != coupling::faux ) )
|| ( ( dynamic == NextConnected ) && ( MoverParameters->Couplers[ TMoverParameters::side::rear ].CouplingFlag != coupling::faux ) ) ){
// stop-gap check to prevent 'detection' of attached vehicles
// which seems to be a side-effect of inaccurate location calculation in 'simple' mode?
// TODO: investigate actual cause
continue;
}
*/
if( Direction > 0 ) { if( Direction > 0 ) {
// jeśli szukanie w kierunku Point2 // jeśli szukanie w kierunku Point2
objectposition = ( dynamic->RaTranslationGet() ) - myposition; // odległogłość tamtego od szukającego objectposition = ( dynamic->RaTranslationGet() ) - myposition; // odległogłość tamtego od szukającego
@@ -1328,16 +1336,23 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance )
// ScanDir - określa kierunek poszukiwania zależnie od zwrotu prędkości // ScanDir - określa kierunek poszukiwania zależnie od zwrotu prędkości
// pojazdu // pojazdu
// ScanDir=1 - od strony Coupler0, ScanDir=-1 - od strony Coupler1 // ScanDir=1 - od strony Coupler0, ScanDir=-1 - od strony Coupler1
int initialdirection = Direction; // zapamiętanie kierunku poszukiwań na torze początkowym, względem sprzęgów auto const initialdirection = Direction; // zapamiętanie kierunku poszukiwań na torze początkowym, względem sprzęgów
TTrackFollower *firstaxle = (initialdirection > 0 ? &Axle0 : &Axle1); // można by to trzymać w trainset /*
TTrack *track = firstaxle->GetTrack(); // tor na którym "stoi" skrajny wózek TTrackFollower const *firstaxle = (initialdirection > 0 ? &Axle0 : &Axle1); // można by to trzymać w trainset
TTrack const *track = firstaxle->GetTrack(); // tor na którym "stoi" skrajny wózek
// (może być inny niż tor pojazdu) // (może być inny niż tor pojazdu)
if( firstaxle->GetDirection() < 0 ) { if( firstaxle->GetDirection() < 0 ) {
// czy oś jest ustawiona w stronę Point1? // czy oś jest ustawiona w stronę Point1?
Direction = -Direction; // jeśli tak, to kierunek szukania będzie przeciwny Direction = -Direction; // jeśli tak, to kierunek szukania będzie przeciwny
} }
// (teraz względem */
// toru) TTrack const *track = RaTrackGet();
if( RaDirectionGet() < 0 ) {
// czy oś jest ustawiona w stronę Point1?
Direction = -Direction;
}
// (teraz względem toru)
int const mycoupler = ( initialdirection < 0 ? 1 : 0 ); // numer sprzęgu do podłączenia w obiekcie szukajacym int const mycoupler = ( initialdirection < 0 ? 1 : 0 ); // numer sprzęgu do podłączenia w obiekcie szukajacym
int foundcoupler { -1 }; // numer sprzęgu w znalezionym obiekcie (znaleziony wypełni) int foundcoupler { -1 }; // numer sprzęgu w znalezionym obiekcie (znaleziony wypełni)
double distance = 0; // przeskanowana odleglość; odległość do zawalidrogi double distance = 0; // przeskanowana odleglość; odległość do zawalidrogi
@@ -1347,9 +1362,9 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance )
// jeśli nie ma na tym samym, szukamy po okolicy szukanie najblizszego toru z jakims obiektem // jeśli nie ma na tym samym, szukamy po okolicy szukanie najblizszego toru z jakims obiektem
// praktycznie przeklejone z TraceRoute()... // praktycznie przeklejone z TraceRoute()...
if (Direction >= 0) // uwzględniamy kawalek przeanalizowanego wcześniej toru if (Direction >= 0) // uwzględniamy kawalek przeanalizowanego wcześniej toru
distance = track->Length() - firstaxle->GetTranslation(); // odległość osi od Point2 toru distance = track->Length() - RaTranslationGet(); // odległość osi od Point2 toru
else else
distance = firstaxle->GetTranslation(); // odległość osi od Point1 toru distance = RaTranslationGet(); // odległość osi od Point1 toru
while (distance < Distance) { while (distance < Distance) {
if (Direction > 0) { if (Direction > 0) {
@@ -1455,6 +1470,14 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance )
// nic nie znalezione, to nie ma przeszkód // nic nie znalezione, to nie ma przeszkód
fTrackBlock = 10000.0; fTrackBlock = 10000.0;
} }
#ifdef EU07_DEBUG_COLLISIONS
// debug collider scans
if( ( PrevConnected != nullptr )
&& ( PrevConnected == NextConnected ) ) {
ErrorLog( "Bad coupling: " + asName + " has the same vehicle detected attached to both couplers" );
}
#endif
} }
//----------ABu: koniec skanowania pojazdow //----------ABu: koniec skanowania pojazdow

View File

@@ -78,7 +78,7 @@ class TAnimValveGear
class TAnimPant class TAnimPant
{ // współczynniki do animacji pantografu { // współczynniki do animacji pantografu
public: public:
vector3 vPos; // Ra: współrzędne punktu zerowego pantografu (X dodatnie dla przedniego) Math3D::vector3 vPos; // Ra: współrzędne punktu zerowego pantografu (X dodatnie dla przedniego)
double fLenL1; // długość dolnego ramienia 1, odczytana z modelu double fLenL1; // długość dolnego ramienia 1, odczytana z modelu
double fLenU1; // długość górnego 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 fLenL2; // długość dolnego ramienia 2, odczytana z modelu
@@ -152,9 +152,9 @@ class TDynamicObject { // klasa pojazdu
friend class opengl_renderer; friend class opengl_renderer;
private: // położenie pojazdu w świecie oraz parametry ruchu private: // położenie pojazdu w świecie oraz parametry ruchu
vector3 vPosition; // Ra: pozycja pojazdu liczona zaraz po przesunięciu Math3D::vector3 vPosition; // Ra: pozycja pojazdu liczona zaraz po przesunięciu
vector3 vCoulpler[ 2 ]; // współrzędne sprzęgów do liczenia zderzeń czołowych Math3D::vector3 vCoulpler[ 2 ]; // współrzędne sprzęgów do liczenia zderzeń czołowych
vector3 vUp, vFront, vLeft; // wektory jednostkowe ustawienia pojazdu Math3D::vector3 vUp, vFront, vLeft; // wektory jednostkowe ustawienia pojazdu
int iDirection; // kierunek pojazdu względem czoła składu (1=zgodny,0=przeciwny) int iDirection; // kierunek pojazdu względem czoła składu (1=zgodny,0=przeciwny)
TTrackShape ts; // parametry toru przekazywane do fizyki TTrackShape ts; // parametry toru przekazywane do fizyki
TTrackParam tp; // parametry toru przekazywane do fizyki TTrackParam tp; // parametry toru przekazywane do fizyki
@@ -163,14 +163,14 @@ private: // położenie pojazdu w świecie oraz parametry ruchu
int iAxleFirst; // numer pierwszej osi w kierunku ruchu (oś wiążąca pojazd z torem i wyzwalająca int iAxleFirst; // numer pierwszej osi w kierunku ruchu (oś wiążąca pojazd z torem i wyzwalająca
// eventy) // eventy)
float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia
vector3 modelRot; // obrot pudła względem świata - do przeanalizowania, czy potrzebne!!! Math3D::vector3 modelRot; // obrot pudła względem świata - do przeanalizowania, czy potrzebne!!!
// bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów // bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów
TDynamicObject * ABuFindNearestObject( TTrack *Track, TDynamicObject *MyPointer, int &CouplNr ); TDynamicObject * ABuFindNearestObject( TTrack *Track, TDynamicObject *MyPointer, int &CouplNr );
public: // parametry położenia pojazdu dostępne publicznie public: // parametry położenia pojazdu dostępne publicznie
std::string asTrack; // nazwa toru początkowego; wywalić? std::string asTrack; // nazwa toru początkowego; wywalić?
std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)" std::string asDestination; // dokąd pojazd ma być kierowany "(stacja):(tor)"
matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli Math3D::matrix4x4 mMatrix; // macierz przekształcenia do renderowania modeli
TMoverParameters *MoverParameters; // parametry fizyki ruchu oraz przeliczanie TMoverParameters *MoverParameters; // parametry fizyki ruchu oraz przeliczanie
// TMoverParameters *pControlled; //wskaźnik do sterowanego członu silnikowego // TMoverParameters *pControlled; //wskaźnik do sterowanego członu silnikowego
TDynamicObject *NextConnected; // pojazd podłączony od strony sprzęgu 1 (kabina -1) TDynamicObject *NextConnected; // pojazd podłączony od strony sprzęgu 1 (kabina -1)
@@ -237,7 +237,7 @@ public: // modele składowe pojazdu
void toggle_lights(); // switch light levels for registered interior sections void toggle_lights(); // switch light levels for registered interior sections
private: // Ra: ciąg dalszy animacji, dopiero do ogarnięcia private: // Ra: ciąg dalszy animacji, dopiero do ogarnięcia
// ABuWozki 060504 // ABuWozki 060504
vector3 bogieRot[2]; // Obroty wozkow w/m korpusu Math3D::vector3 bogieRot[2]; // Obroty wozkow w/m korpusu
TSubModel *smBogie[2]; // Wyszukiwanie max 2 wozkow TSubModel *smBogie[2]; // Wyszukiwanie max 2 wozkow
TSubModel *smWahacze[4]; // wahacze (np. nogi, dźwignia w drezynie) TSubModel *smWahacze[4]; // wahacze (np. nogi, dźwignia w drezynie)
TSubModel *smBrakeMode; // Ra 15-01: nastawa hamulca też TSubModel *smBrakeMode; // Ra 15-01: nastawa hamulca też
@@ -249,7 +249,7 @@ public: // modele składowe pojazdu
TSubModel *smBuforLewy[2]; TSubModel *smBuforLewy[2];
TSubModel *smBuforPrawy[2]; TSubModel *smBuforPrawy[2];
TAnimValveGear *pValveGear; TAnimValveGear *pValveGear;
vector3 vFloor; // podłoga dla ładunku Math3D::vector3 vFloor; // podłoga dla ładunku
public: public:
TAnim *pants; // indeks obiektu animującego dla pantografu 0 TAnim *pants; // indeks obiektu animującego dla pantografu 0
double NoVoltTime; // czas od utraty zasilania double NoVoltTime; // czas od utraty zasilania
@@ -264,7 +264,7 @@ public: // modele składowe pojazdu
void ABuLittleUpdate(double ObjSqrDist); void ABuLittleUpdate(double ObjSqrDist);
bool btnOn; // ABu: czy byly uzywane buttony, jesli tak, to po renderingu wylacz bool btnOn; // ABu: czy byly uzywane buttony, jesli tak, to po renderingu wylacz
// bo ten sam model moze byc jeszcze wykorzystany przez inny obiekt! // bo ten sam model moze byc jeszcze wykorzystany przez inny obiekt!
double ComputeRadius(vector3 p1, vector3 p2, vector3 p3, vector3 p4); double ComputeRadius( Math3D::vector3 p1, Math3D::vector3 p2, Math3D::vector3 p3, Math3D::vector3 p4);
TButton btCoupler1; // sprzegi TButton btCoupler1; // sprzegi
TButton btCoupler2; TButton btCoupler2;
@@ -337,7 +337,7 @@ public: // modele składowe pojazdu
double eng_turbo; double eng_turbo;
void ABuBogies(); void ABuBogies();
void ABuModelRoll(); void ABuModelRoll();
vector3 modelShake; Math3D::vector3 modelShake;
bool renderme; // yB - czy renderowac bool renderme; // yB - czy renderowac
// TRealSound sBrakeAcc; //dźwięk przyspieszacza // TRealSound sBrakeAcc; //dźwięk przyspieszacza
@@ -361,7 +361,7 @@ public: // modele składowe pojazdu
void ABuScanObjects(int ScanDir, double ScanDist); void ABuScanObjects(int ScanDir, double ScanDist);
protected: protected:
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack *Track, int const Direction, int const Mycoupler ); TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler );
void ABuCheckMyTrack(); void ABuCheckMyTrack();
public: public:
@@ -406,7 +406,7 @@ public: // modele składowe pojazdu
int &CouplNr); int &CouplNr);
TDynamicObject * GetFirstDynamic(int cpl_type, int cf = 1); TDynamicObject * GetFirstDynamic(int cpl_type, int cf = 1);
// TDynamicObject* GetFirstCabDynamic(int cpl_type); // TDynamicObject* GetFirstCabDynamic(int cpl_type);
void ABuSetModelShake(vector3 mShake); void ABuSetModelShake( Math3D::vector3 mShake);
// McZapkie-010302 // McZapkie-010302
TController *Mechanik; TController *Mechanik;
@@ -437,31 +437,31 @@ public: // modele składowe pojazdu
void Move(double fDistance); void Move(double fDistance);
void FastMove(double fDistance); void FastMove(double fDistance);
void RenderSounds(); void RenderSounds();
inline vector3 GetPosition() const inline Math3D::vector3 GetPosition() const
{ {
return vPosition; return vPosition;
}; };
inline vector3 HeadPosition() inline Math3D::vector3 HeadPosition()
{ {
return vCoulpler[iDirection ^ 1]; return vCoulpler[iDirection ^ 1];
}; // pobranie współrzędnych czoła }; // pobranie współrzędnych czoła
inline vector3 RearPosition() inline Math3D::vector3 RearPosition()
{ {
return vCoulpler[iDirection]; return vCoulpler[iDirection];
}; // pobranie współrzędnych tyłu }; // pobranie współrzędnych tyłu
inline vector3 AxlePositionGet() inline Math3D::vector3 AxlePositionGet()
{ {
return iAxleFirst ? Axle1.pPosition : Axle0.pPosition; return iAxleFirst ? Axle1.pPosition : Axle0.pPosition;
}; };
inline vector3 VectorFront() const inline Math3D::vector3 VectorFront() const
{ {
return vFront; return vFront;
}; };
inline vector3 VectorUp() inline Math3D::vector3 VectorUp()
{ {
return vUp; return vUp;
}; };
inline vector3 VectorLeft() const inline Math3D::vector3 VectorLeft() const
{ {
return vLeft; return vLeft;
}; };

View File

@@ -673,7 +673,7 @@ double TEvent::ValueGet(int n)
return 0.0; // inne eventy się nie liczą return 0.0; // inne eventy się nie liczą
}; };
vector3 TEvent::PositionGet() vector3 TEvent::PositionGet() const
{ // pobranie współrzędnych eventu { // pobranie współrzędnych eventu
switch (Type) switch (Type)
{ // { //

View File

@@ -108,7 +108,7 @@ class TEvent // zmienne: ev*
std::string CommandGet(); std::string CommandGet();
TCommandType Command(); TCommandType Command();
double ValueGet(int n); double ValueGet(int n);
vector3 PositionGet(); vector3 PositionGet() const;
bool StopCommand(); bool StopCommand();
void StopCommandSent(); void StopCommandSent();
void Append(TEvent *e); void Append(TEvent *e);

View File

@@ -1094,6 +1094,7 @@ void TMoverParameters::CollisionDetect(int CouplerN, double dt)
coupler.Connected->Couplers[0].CouplingFlag = 0; coupler.Connected->Couplers[0].CouplingFlag = 0;
break; break;
} }
WriteLog( "Bad driving: " + Name + " broke a coupler" );
} }
} }
} }
@@ -1268,11 +1269,13 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
AccN = g * Shape.dHrail / TrackW; AccN = g * Shape.dHrail / TrackW;
// szarpanie // szarpanie
if (FuzzyLogic((10.0 + Track.DamageFlag) * Mass * Vel / Vmax, 500000.0, #ifdef EU07_USE_FUZZYLOGIC
p_accn)) // Ra: czemu tu masa bez ładunku? if( FuzzyLogic( ( 10.0 + Track.DamageFlag ) * Mass * Vel / Vmax, 500000.0, p_accn ) ) {
AccV = sqrt((1.0 + Track.DamageFlag) * Random(floor(50.0 * Mass / 1000000.0)) * Vel / // Ra: czemu tu masa bez ładunku?
(Vmax * (10.0 + (Track.QualityFlag & 31)))); AccV /= ( 2.0 * 0.95 + 2.0 * Random() * 0.1 ); // 95-105% of base modifier (2.0)
}
else else
#endif
AccV = AccV / 2.0; AccV = AccV / 2.0;
if (AccV > 1.0) if (AccV > 1.0)
@@ -1438,12 +1441,13 @@ double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape
// else AccN:=g*Shape.dHrail/TrackW; // else AccN:=g*Shape.dHrail/TrackW;
// szarpanie} // szarpanie}
if (FuzzyLogic((10.0 + Track.DamageFlag) * Mass * Vel / Vmax, 500000.0, p_accn)) #ifdef EU07_USE_FUZZYLOGIC
{ if( FuzzyLogic( ( 10.0 + Track.DamageFlag ) * Mass * Vel / Vmax, 500000.0, p_accn ) ) {
AccV = sqrt((1.0 + Track.DamageFlag) * Random(floor(50.0 * Mass / 1000000.0)) * Vel / // Ra: czemu tu masa bez ładunku?
(Vmax * (10.0 + (Track.QualityFlag & 31)))); // Trunc na floor, czy dobrze? AccV /= ( 2.0 * 0.95 + 2.0 * Random() * 0.1 ); // 95-105% of base modifier (2.0)
} }
else else
#endif
AccV = AccV / 2.0; AccV = AccV / 2.0;
if (AccV > 1.0) if (AccV > 1.0)
@@ -3670,6 +3674,7 @@ double TMoverParameters::ComputeMass(void)
void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
{ {
int b; int b;
double Fwheels = 0.0;
if (PhysicActivation) if (PhysicActivation)
{ {
@@ -3729,19 +3734,35 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
else else
FTrain = 0; FTrain = 0;
Fb = BrakeForce(RunningTrack); Fb = BrakeForce(RunningTrack);
Fwheels = FTrain - Fb * Sign(V);
if( ( Vel > 0.001 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test if( ( Vel > 0.001 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test
&& ( std::max( std::abs( FTrain ), Fb ) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) // poslizg && ( std::abs(Fwheels) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) // poslizg
{ {
SlippingWheels = true; SlippingWheels = true;
} }
if( true == SlippingWheels ) { if( true == SlippingWheels ) {
// TrainForce:=TrainForce-Fb; // TrainForce:=TrainForce-Fb;
nrot = ComputeRotatingWheel((FTrain - Fb * Sign(V) - FStand) / NAxles - double temp_nrot = ComputeRotatingWheel(Fwheels -
Sign(nrot * M_PI * WheelDiameter - V) * Sign(nrot * M_PI * WheelDiameter - V) *
Adhesive(RunningTrack.friction) * TotalMass, Adhesive(RunningTrack.friction) * TotalMassxg,
dt, nrot); dt, nrot);
FTrain = Sign(FTrain) * TotalMassxg * Adhesive(RunningTrack.friction); Fwheels = Sign(nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction);
Fb = std::min(Fb, TotalMassxg * Adhesive(RunningTrack.friction)); if (Fwheels*Sign(V)>0)
{
FTrain = Fwheels - Fb;
}
else
{
Fb = FTrain - Fwheels;
}
if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0)
{
SlippingWheels = false;
temp_nrot = V / M_PI / WheelDiameter;
}
nrot = temp_nrot;
} }
// else SlippingWheels:=false; // else SlippingWheels:=false;
// FStand:=0; // FStand:=0;
@@ -3750,7 +3771,7 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
(Couplers[b].CouplerType<>Articulated)*/ (Couplers[b].CouplerType<>Articulated)*/
{ // doliczenie sił z innych pojazdów { // doliczenie sił z innych pojazdów
Couplers[b].CForce = CouplerForce(b, dt); Couplers[b].CForce = CouplerForce(b, dt);
FTrain += Couplers[b].CForce; FTrain += Couplers[b].CForce;
} }
else else
Couplers[b].CForce = 0; Couplers[b].CForce = 0;
@@ -3884,16 +3905,6 @@ double TMoverParameters::BrakeForce(const TTrackParam &Track)
} }
else else
UnitBrakeForce = K * 1000.0; UnitBrakeForce = K * 1000.0;
if (((double)NBpA * UnitBrakeForce > TotalMassxg * Adhesive(RunningTrack.friction) / NAxles) &&
(abs(V) > 0.001))
// poslizg
{
// Fb = Adhesive(Track.friction) * Mass * g;
SlippingWheels = true;
}
//{ else
// begin
//{ SlippingWheels:=false;}
// if (LocalBrake=ManualBrake)or(MBrake=true)) and (BrakePress<0.3) then // if (LocalBrake=ManualBrake)or(MBrake=true)) and (BrakePress<0.3) then
// Fb:=UnitBrakeForce*NBpA {ham. reczny dziala na jedna os} // Fb:=UnitBrakeForce*NBpA {ham. reczny dziala na jedna os}
// else //yB: to nie do konca ma sens, ponieważ ręczny w wagonie działa na jeden cylinder // else //yB: to nie do konca ma sens, ponieważ ręczny w wagonie działa na jeden cylinder
@@ -3929,7 +3940,10 @@ double TMoverParameters::FrictionForce(double R, int TDamage)
// ************************************************************************************************* // *************************************************************************************************
double TMoverParameters::Adhesive(double staticfriction) double TMoverParameters::Adhesive(double staticfriction)
{ {
double adhesion; double adhesion = 0.0;
const double adh_factor = 0.25; //współczynnik określający, jak bardzo spada tarcie przy poślizgu
const double slipfactor = 0.33; //współczynnik określający, jak szybko spada tarcie przy poślizgu
const double sandfactor = 1.25; //współczynnik określający, jak mocno pomaga piasek
/* /*
// ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS? // ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS?
// w kazdym razie zaciemni kod na pewno :) // w kazdym razie zaciemni kod na pewno :)
@@ -3952,6 +3966,7 @@ double TMoverParameters::Adhesive(double staticfriction)
// WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3 // WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3
return adhesion; return adhesion;
*/ */
/* //wersja druga
if( true == SlippingWheels ) { if( true == SlippingWheels ) {
if( true == SandDose ) { adhesion = 0.48; } if( true == SandDose ) { adhesion = 0.48; }
@@ -3962,7 +3977,12 @@ double TMoverParameters::Adhesive(double staticfriction)
if( true == SandDose ) { adhesion = std::max( staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ) * 1.1, 0.48 ); } if( true == SandDose ) { adhesion = std::max( staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ) * 1.1, 0.48 ); }
else { adhesion = staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ); } else { adhesion = staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ); }
} }
adhesion *= ( 11.0 - 2 * Random() ) / 10.0; adhesion *= ( 11.0 - 2 * Random() ) / 10.0; */
//wersja3 by youBy - uwzględnia naturalne mikropoślizgi i wpływ piasecznicy, usuwa losowość z pojazdu
double Vwheels = nrot * M_PI * WheelDiameter; // predkosc liniowa koła wynikająca z obrotowej
double deltaV = V - Vwheels; //poślizg - różnica prędkości w punkcie styku koła i szyny
deltaV = std::max(0.0, std::abs(deltaV) - 0.25); //mikropoślizgi do ok. 0,25 m/s nie zrywają przyczepności
adhesion = staticfriction * (28 + Vwheels) / (14 + Vwheels) * ((SandDose? sandfactor : 1) - (1 - adh_factor)*(deltaV / (deltaV + slipfactor)));
return adhesion; return adhesion;
} }

View File

@@ -1489,6 +1489,8 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
*/ */
// we rely on the SUB chunk coming before the vertex data, and on the overall vertex count matching the size of data in the chunk. // we rely on the SUB chunk coming before the vertex data, and on the overall vertex count matching the size of data in the chunk.
// geometry associated with chunks isn't stored in the same order as the chunks themselves, so we need to sort that out first // geometry associated with chunks isn't stored in the same order as the chunks themselves, so we need to sort that out first
if( Root == nullptr )
throw std::runtime_error( "e3d: VNT chunk encountered before SUB chunk" );
std::vector< std::pair<int, int> > submodeloffsets; // vertex data offset, submodel index std::vector< std::pair<int, int> > submodeloffsets; // vertex data offset, submodel index
submodeloffsets.reserve( iSubModelsCount ); submodeloffsets.reserve( iSubModelsCount );
for( int submodelindex = 0; submodelindex < iSubModelsCount; ++submodelindex ) { for( int submodelindex = 0; submodelindex < iSubModelsCount; ++submodelindex ) {

View File

@@ -64,10 +64,10 @@ bool TPythonInterpreter::loadClassFile( std::string const &lookupPath, std::stri
if (sourceFile != nullptr) if (sourceFile != nullptr)
{ {
fseek(sourceFile, 0, SEEK_END); fseek(sourceFile, 0, SEEK_END);
long fsize = ftell(sourceFile); auto const fsize = ftell(sourceFile);
char *buffer = (char *)calloc(fsize + 1, sizeof(char)); char *buffer = (char *)calloc(fsize + 1, sizeof(char));
fseek(sourceFile, 0, SEEK_SET); fseek(sourceFile, 0, SEEK_SET);
size_t freaded = fread(buffer, sizeof(char), fsize, sourceFile); auto const freaded = fread(buffer, sizeof(char), fsize, sourceFile);
buffer[freaded] = 0; // z jakiegos powodu czytamy troche mniej i trzczeba dodac konczace buffer[freaded] = 0; // z jakiegos powodu czytamy troche mniej i trzczeba dodac konczace
// zero do bufora (mimo ze calloc teoretycznie powiniene zwrocic // zero do bufora (mimo ze calloc teoretycznie powiniene zwrocic
// wyzerowana pamiec) // wyzerowana pamiec)

View File

@@ -21,20 +21,17 @@ http://mozilla.org/MPL/2.0/.
// 110806 Ra: odwrócone mapowanie wzdłuż - Point1 == 1.0 // 110806 Ra: odwrócone mapowanie wzdłuż - Point1 == 1.0
TSegment::TSegment(TTrack *owner) : TSegment::TSegment(TTrack *owner) :
pOwner( owner ) pOwner( owner )
{ {}
fAngle[ 0 ] = 0.0;
fAngle[ 1 ] = 0.0;
};
TSegment::~TSegment() TSegment::~TSegment()
{ {
SafeDeleteArray(fTsBuffer); SafeDeleteArray(fTsBuffer);
}; }
bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1, double fNewRoll2) bool TSegment::Init(Math3D::vector3 NewPoint1, Math3D::vector3 NewPoint2, double fNewStep, double fNewRoll1, double fNewRoll2)
{ // wersja dla prostego - wyliczanie punktów kontrolnych { // wersja dla prostego - wyliczanie punktów kontrolnych
vector3 dir; Math3D::vector3 dir;
// NOTE: we're enforcing division also for straight track, to ensure dense enough mesh for per-vertex lighting // NOTE: we're enforcing division also for straight track, to ensure dense enough mesh for per-vertex lighting
/* /*
@@ -55,9 +52,7 @@ bool TSegment::Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, doubl
} }
}; };
bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointIn, bool TSegment::Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, Math3D::vector3 NewCPointIn, Math3D::vector3 &NewPoint2, double fNewStep, double fNewRoll1, double fNewRoll2, bool bIsCurve)
vector3 &NewPoint2, double fNewStep, double fNewRoll1, double fNewRoll2,
bool bIsCurve)
{ // wersja uniwersalna (dla krzywej i prostego) { // wersja uniwersalna (dla krzywej i prostego)
Point1 = NewPoint1; Point1 = NewPoint1;
CPointOut = NewCPointOut; CPointOut = NewCPointOut;
@@ -77,7 +72,7 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
// mieć moment wypoziomowania, ale musi on być również podniesiony. // mieć moment wypoziomowania, ale musi on być również podniesiony.
if (fRoll1 != 0.0) if (fRoll1 != 0.0)
{ // tylko jeśli jest przechyłka { // tylko jeśli jest przechyłka
double w1 = fabs(sin(fRoll1) * 0.75); // 0.5*w2+0.0325; //0.75m dla 1.435 double w1 = std::abs(std::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 Point1.y += w1; // modyfikacja musi być przed policzeniem dalszych parametrów
if (bCurve) if (bCurve)
CPointOut.y += w1; // prosty ma wektory jednostkowe CPointOut.y += w1; // prosty ma wektory jednostkowe
@@ -85,7 +80,7 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
} }
if (fRoll2 != 0.0) if (fRoll2 != 0.0)
{ {
double w2 = fabs(sin(fRoll2) * 0.75); // 0.5*w2+0.0325; //0.75m dla 1.435 double w2 = std::abs(std::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 Point2.y += w2; // modyfikacja musi być przed policzeniem dalszych parametrów
if (bCurve) if (bCurve)
CPointIn.y += w2; // prosty ma wektory jednostkowe CPointIn.y += w2; // prosty ma wektory jednostkowe
@@ -137,12 +132,12 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
return true; return true;
} }
vector3 TSegment::GetFirstDerivative(double fTime) Math3D::vector3 TSegment::GetFirstDerivative(double const fTime) const
{ {
double fOmTime = 1.0 - fTime; double fOmTime = 1.0 - fTime;
double fPowTime = fTime; double fPowTime = fTime;
vector3 kResult = fOmTime * (CPointOut - Point1); Math3D::vector3 kResult = fOmTime * (CPointOut - Point1);
// int iDegreeM1 = 3 - 1; // int iDegreeM1 = 3 - 1;
@@ -156,7 +151,7 @@ vector3 TSegment::GetFirstDerivative(double fTime)
return kResult; return kResult;
} }
double TSegment::RombergIntegral(double fA, double fB) double TSegment::RombergIntegral(double const fA, double const fB) const
{ {
double fH = fB - fA; double fH = fB - fA;
@@ -188,7 +183,7 @@ double TSegment::RombergIntegral(double fA, double fB)
return ms_apfRom[0][ms_iOrder - 1]; return ms_apfRom[0][ms_iOrder - 1];
} }
double TSegment::GetTFromS(double s) double TSegment::GetTFromS(double const s) const
{ {
// initial guess for Newton's method // initial guess for Newton's method
double fTolerance = 0.001; double fTolerance = 0.001;
@@ -216,41 +211,83 @@ double TSegment::GetTFromS(double s)
return fTime; return fTime;
}; };
vector3 TSegment::RaInterpolate(double t) Math3D::vector3 TSegment::RaInterpolate(double const t) const
{ // wyliczenie XYZ na krzywej Beziera z użyciem współczynników { // wyliczenie XYZ na krzywej Beziera z użyciem współczynników
return t * (t * (t * vA + vB) + vC) + Point1; // 9 mnożeń, 9 dodawań return t * (t * (t * vA + vB) + vC) + Point1; // 9 mnożeń, 9 dodawań
}; };
vector3 TSegment::RaInterpolate0(double t) Math3D::vector3 TSegment::RaInterpolate0(double const t) const
{ // wyliczenie XYZ na krzywej Beziera, na użytek liczenia długości nie jest dodawane Point1 { // 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ń return t * (t * (t * vA + vB) + vC); // 9 mnożeń, 6 dodawań
}; };
double TSegment::ComputeLength() // McZapkie-150503: dlugosc miedzy punktami krzywej double TSegment::ComputeLength() const // McZapkie-150503: dlugosc miedzy punktami krzywej
{ // obliczenie długości krzywej Beziera za pomocą interpolacji odcinkami { // obliczenie długości krzywej Beziera za pomocą interpolacji odcinkami
// Ra: zamienić na liczenie rekurencyjne średniej z cięciwy i łamanej po kontrolnych // 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 // Ra: koniec rekurencji jeśli po podziale suma długości nie różni się więcej niż 0.5mm od
// poprzedniej // poprzedniej
// Ra: ewentualnie rozpoznać łuk okręgu płaskiego i liczyć ze wzoru na długość łuku // Ra: ewentualnie rozpoznać łuk okręgu płaskiego i liczyć ze wzoru na długość łuku
double t, l = 0; double t, l = 0;
vector3 last = vector3(0, 0, 0); // długość liczona po przesunięciu odcinka do początku układu Math3D::vector3 last = Math3D::vector3(0, 0, 0); // długość liczona po przesunięciu odcinka do początku układu
vector3 tmp = Point2 - Point1; Math3D::vector3 tmp = Point2 - Point1;
int m = 20.0 * tmp.Length(); // było zawsze do 10000, teraz jest liczone odcinkami po około 5cm 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++) for (int i = 1; i <= m; i++)
{ {
t = double(i) / double(m); // wyznaczenie parametru na krzywej z przedziału (0,1> t = double(i) / double(m); // wyznaczenie parametru na krzywej z przedziału (0,1>
// tmp=Interpolate(t,p1,cp1,cp2,p2); // tmp=Interpolate(t,p1,cp1,cp2,p2);
tmp = RaInterpolate0(t); // obliczenie punktu dla tego parametru tmp = RaInterpolate0(t); // obliczenie punktu dla tego parametru
t = vector3(tmp - last).Length(); // obliczenie długości wektora t = Math3D::vector3(tmp - last).Length(); // obliczenie długości wektora
l += t; // zwiększenie wyliczanej długości l += t; // zwiększenie wyliczanej długości
last = tmp; last = tmp;
} }
return (l); return (l);
} }
// finds point on segment closest to specified point in 3d space. returns: point on segment as value in range 0-1
double
TSegment::find_nearest_point( glm::dvec3 const &Point ) const {
if( ( false == bCurve ) || ( iSegCount == 1 ) ) {
// for straight track just treat it as a single segment
return
nearest_segment_point(
glm::dvec3{ FastGetPoint_0() },
glm::dvec3{ FastGetPoint_1() },
Point );
}
else {
// for curves iterate through segment chunks, and find the one which gives us the least distance to the specified point
double distance = std::numeric_limits<double>::max();
double nearest;
// NOTE: we're reusing already created segment chunks, which are created based on splinefidelity setting
// this means depending on splinefidelity the results can be potentially slightly different
for( int segmentidx = 0; segmentidx < iSegCount; ++segmentidx ) {
auto const segmentpoint =
clamp(
nearest_segment_point(
glm::dvec3{ FastGetPoint( fTsBuffer[ segmentidx ] ) },
glm::dvec3{ FastGetPoint( fTsBuffer[ segmentidx + 1 ] ) },
Point ) // point in range 0-1 on current segment
* ( fTsBuffer[ segmentidx + 1 ] - fTsBuffer[ segmentidx ] ) // segment length
+ fTsBuffer[ segmentidx ], // segment offset
0.0, 1.0 ); // we clamp the range in case there's some floating point math inaccuracies
auto const segmentdistance = glm::length2( Point - glm::dvec3{ FastGetPoint( segmentpoint ) } );
if( segmentdistance < distance ) {
nearest = segmentpoint;
distance = segmentdistance;
}
}
//
return nearest;
}
}
const double fDirectionOffset = 0.1; // długość wektora do wyliczenia kierunku const double fDirectionOffset = 0.1; // długość wektora do wyliczenia kierunku
vector3 TSegment::GetDirection(double fDistance) Math3D::vector3 TSegment::GetDirection(double const fDistance) const
{ // takie toporne liczenie pochodnej dla podanego dystansu od Point1 { // takie toporne liczenie pochodnej dla podanego dystansu od Point1
double t1 = GetTFromS(fDistance - fDirectionOffset); double t1 = GetTFromS(fDistance - fDirectionOffset);
if (t1 <= 0.0) if (t1 <= 0.0)
@@ -261,7 +298,7 @@ vector3 TSegment::GetDirection(double fDistance)
return (FastGetPoint(t2) - FastGetPoint(t1)); return (FastGetPoint(t2) - FastGetPoint(t1));
} }
vector3 TSegment::FastGetDirection(double fDistance, double fOffset) Math3D::vector3 TSegment::FastGetDirection(double fDistance, double fOffset)
{ // takie toporne liczenie pochodnej dla parametru 0.0÷1.0 { // takie toporne liczenie pochodnej dla parametru 0.0÷1.0
double t1 = fDistance - fOffset; double t1 = fDistance - fOffset;
if (t1 <= 0.0) if (t1 <= 0.0)
@@ -272,7 +309,7 @@ vector3 TSegment::FastGetDirection(double fDistance, double fOffset)
return (FastGetPoint(t2) - FastGetPoint(t1)); return (FastGetPoint(t2) - FastGetPoint(t1));
} }
vector3 TSegment::GetPoint(double fDistance) Math3D::vector3 TSegment::GetPoint(double const fDistance) const
{ // wyliczenie współrzędnych XYZ na torze w odległości (fDistance) od Point1 { // wyliczenie współrzędnych XYZ na torze w odległości (fDistance) od Point1
if (bCurve) if (bCurve)
{ // można by wprowadzić uproszczony wzór dla okręgów płaskich { // można by wprowadzić uproszczony wzór dla okręgów płaskich
@@ -287,7 +324,7 @@ vector3 TSegment::GetPoint(double fDistance)
} }
}; };
void TSegment::RaPositionGet(double fDistance, vector3 &p, vector3 &a) void TSegment::RaPositionGet(double const fDistance, Math3D::vector3 &p, Math3D::vector3 &a) const
{ // ustalenie pozycji osi na torze, przechyłki, pochylenia i kierunku jazdy { // ustalenie pozycji osi na torze, przechyłki, pochylenia i kierunku jazdy
if (bCurve) if (bCurve)
{ // można by wprowadzić uproszczony wzór dla okręgów płaskich { // można by wprowadzić uproszczony wzór dla okręgów płaskich
@@ -309,13 +346,16 @@ void TSegment::RaPositionGet(double fDistance, vector3 &p, vector3 &a)
} }
}; };
vector3 TSegment::FastGetPoint(double t) Math3D::vector3 TSegment::FastGetPoint(double const t) const
{ {
// return (bCurve?Interpolate(t,Point1,CPointOut,CPointIn,Point2):((1.0-t)*Point1+(t)*Point2)); // return (bCurve?Interpolate(t,Point1,CPointOut,CPointIn,Point2):((1.0-t)*Point1+(t)*Point2));
return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2)); return (
( ( true == bCurve ) || ( iSegCount != 1 ) ) ?
RaInterpolate( t ) :
interpolate( Point1, Point2, t ) );
} }
bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, vector3 **p, bool bRender) bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, Math3D::vector3 **p, bool bRender)
{ // generowanie trójkątów dla odcinka trajektorii ruchu { // generowanie trójkątów dla odcinka trajektorii ruchu
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku // standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli // po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
@@ -325,7 +365,7 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
if( !fTsBuffer ) if( !fTsBuffer )
return false; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę return false; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm; Math3D::vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
double s, step, fOffset, tv1, tv2, t, fEnd; double s, step, fOffset, tv1, tv2, t, fEnd;
bool const trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości bool const trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
iNumShapePoints = std::abs( iNumShapePoints ); iNumShapePoints = std::abs( iNumShapePoints );
@@ -341,7 +381,7 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
fOffset = 0.1 / fLength; // pierwsze 10cm fOffset = 0.1 / fLength; // pierwsze 10cm
pos1 = FastGetPoint( t ); // wektor początku segmentu pos1 = FastGetPoint( t ); // wektor początku segmentu
dir = FastGetDirection( t, fOffset ); // wektor kierunku dir = FastGetDirection( t, fOffset ); // wektor kierunku
parallel1 = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny parallel1 = Normalize( Math3D::vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
if( iEnd == 0 ) if( iEnd == 0 )
iEnd = iSegCount; iEnd = iSegCount;
fEnd = fLength * double( iEnd ) / double( iSegCount ); fEnd = fLength * double( iEnd ) / double( iSegCount );
@@ -371,7 +411,7 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
t = fTsBuffer[ i ]; // szybsze od GetTFromS(s); t = fTsBuffer[ i ]; // szybsze od GetTFromS(s);
pos2 = FastGetPoint( t ); pos2 = FastGetPoint( t );
dir = FastGetDirection( t, fOffset ); // nowy wektor kierunku dir = FastGetDirection( t, fOffset ); // nowy wektor kierunku
parallel2 = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny parallel2 = Normalize( Math3D::vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
if( trapez ) { if( trapez ) {
for( int j = 0; j < iNumShapePoints; ++j ) { for( int j = 0; j < iNumShapePoints; ++j ) {
@@ -453,7 +493,7 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
void TSegment::Render() void TSegment::Render()
{ {
vector3 pt; Math3D::vector3 pt;
GfxRenderer.Bind_Material( null_handle ); GfxRenderer.Bind_Material( null_handle );
if (bCurve) if (bCurve)

148
Segment.h
View File

@@ -7,24 +7,19 @@ obtain one at
http://mozilla.org/MPL/2.0/. http://mozilla.org/MPL/2.0/.
*/ */
#ifndef SegmentH #pragma once
#define SegmentH
/*
#include "VBO.h"
*/
#include "openglgeometrybank.h" #include "openglgeometrybank.h"
#include "dumb3d.h" #include "dumb3d.h"
#include "Classes.h" #include "Classes.h"
#include "usefull.h" #include "usefull.h"
using namespace Math3D;
// 110405 Ra: klasa punktów przekroju z normalnymi // 110405 Ra: klasa punktów przekroju z normalnymi
class vector6 : public vector3 class vector6 : public Math3D::vector3
{ // punkt przekroju wraz z wektorem normalnym { // punkt przekroju wraz z wektorem normalnym
public: public:
vector3 n; Math3D::vector3 n;
vector6() vector6()
{ {
x = y = z = n.x = n.z = 0.0; x = y = z = n.x = n.z = 0.0;
@@ -54,7 +49,7 @@ class vector6 : public vector3
class TSegment class TSegment
{ // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny) { // aproksymacja toru (zwrotnica ma dwa takie, jeden z nich jest aktywny)
private: private:
vector3 Point1, CPointOut, CPointIn, Point2; Math3D::vector3 Point1, CPointOut, CPointIn, Point2;
double fRoll1 = 0.0, double fRoll1 = 0.0,
fRoll2 = 0.0; // przechyłka na końcach fRoll2 = 0.0; // przechyłka na końcach
double fLength = 0.0; // długość policzona double fLength = 0.0; // długość policzona
@@ -63,63 +58,92 @@ class TSegment
int iSegCount = 0; // ilość odcinków do rysowania krzywej int iSegCount = 0; // ilość odcinków do rysowania krzywej
double fDirection = 0.0; // Ra: kąt prostego w planie; dla łuku kąt od Point1 double fDirection = 0.0; // Ra: kąt prostego w planie; dla łuku kąt od Point1
double fStoop = 0.0; // Ra: kąt wzniesienia; dla łuku od Point1 double fStoop = 0.0; // Ra: kąt wzniesienia; dla łuku od Point1
vector3 vA, vB, vC; // współczynniki wielomianów trzeciego stopnia vD==Point1 Math3D::vector3 vA, vB, vC; // współczynniki wielomianów trzeciego stopnia vD==Point1
TTrack *pOwner = nullptr; // wskaźnik na właściciela TTrack *pOwner = nullptr; // wskaźnik na właściciela
double fAngle[2]; // kąty zakończenia drogi na przejazdach double fAngle[ 2 ] = { 0.0, 0.0 }; // kąty zakończenia drogi na przejazdach
vector3 GetFirstDerivative(double fTime); Math3D::vector3
double RombergIntegral(double fA, double fB); GetFirstDerivative(double const fTime) const;
double GetTFromS(double s); double
vector3 RaInterpolate(double t); RombergIntegral(double const fA, double const fB) const;
vector3 RaInterpolate0(double t); double
public: GetTFromS(double const s) const;
Math3D::vector3
RaInterpolate(double const t) const;
Math3D::vector3
RaInterpolate0(double const t) const;
public:
bool bCurve = false; bool bCurve = false;
TSegment(TTrack *owner); TSegment(TTrack *owner);
~TSegment(); ~TSegment();
bool Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1 = 0, double fNewRoll2 = 0); bool
bool Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointIn, vector3 &NewPoint2, Init( Math3D::vector3 NewPoint1, Math3D::vector3 NewPoint2, double fNewStep, double fNewRoll1 = 0, double fNewRoll2 = 0);
double fNewStep, double fNewRoll1 = 0, double fNewRoll2 = 0, bool bIsCurve = true); bool
inline double ComputeLength(); // McZapkie-150503 Init( Math3D::vector3 &NewPoint1, Math3D::vector3 NewCPointOut, Math3D::vector3 NewCPointIn, Math3D::vector3 &NewPoint2, double fNewStep, double fNewRoll1 = 0, double fNewRoll2 = 0, bool bIsCurve = true);
inline vector3 GetDirection1() { double
return bCurve ? CPointOut - Point1 : CPointOut; }; ComputeLength() const; // McZapkie-150503
inline vector3 GetDirection2() { // finds point on segment closest to specified point in 3d space. returns: point on segment as value in range 0-1
return bCurve ? CPointIn - Point2 : CPointIn; }; double
vector3 GetDirection(double fDistance); find_nearest_point( glm::dvec3 const &Point ) const;
vector3 GetDirection() { inline
return CPointOut; }; Math3D::vector3
vector3 FastGetDirection(double fDistance, double fOffset); GetDirection1() const {
vector3 GetPoint(double fDistance); return bCurve ? CPointOut - Point1 : CPointOut; };
void RaPositionGet(double fDistance, vector3 &p, vector3 &a); inline
vector3 FastGetPoint(double t); Math3D::vector3
inline vector3 FastGetPoint_0() { GetDirection2() const {
return Point1; }; return bCurve ? CPointIn - Point2 : CPointIn; };
inline vector3 FastGetPoint_1() { Math3D::vector3
return Point2; }; GetDirection(double const fDistance) const;
inline double GetRoll(double const Distance) { inline
return interpolate( fRoll1, fRoll2, Distance / fLength ); } Math3D::vector3
void GetRolls(double &r1, double &r2) { GetDirection() const {
// pobranie przechyłek (do generowania trójkątów) return CPointOut; };
r1 = fRoll1; Math3D::vector3
r2 = fRoll2; } FastGetDirection(double const fDistance, double const fOffset);
bool RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, vector3 **p = nullptr, bool bRender = true); Math3D::vector3
void Render(); GetPoint(double const fDistance) const;
inline double GetLength() { void
return fLength; }; RaPositionGet(double const fDistance, Math3D::vector3 &p, Math3D::vector3 &a) const;
void MoveMe(vector3 pPosition) Math3D::vector3
{ FastGetPoint(double const t) const;
Point1 += pPosition; inline
Point2 += pPosition; Math3D::vector3
if (bCurve) FastGetPoint_0() const {
{ return Point1; };
CPointIn += pPosition; inline
CPointOut += pPosition; Math3D::vector3
} FastGetPoint_1() const {
} return Point2; };
int RaSegCount() { inline
return fTsBuffer ? iSegCount : 1; }; double
void AngleSet(int i, double a) { GetRoll(double const Distance) const {
fAngle[i] = a; }; return interpolate( fRoll1, fRoll2, Distance / fLength ); }
inline
void
GetRolls(double &r1, double &r2) const {
// pobranie przechyłek (do generowania trójkątów)
r1 = fRoll1;
r2 = fRoll2; }
bool
RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, Math3D::vector3 **p = nullptr, bool bRender = true);
void
Render();
inline
double
GetLength() const {
return fLength; };
inline
int
RaSegCount() const {
return fTsBuffer ? iSegCount : 1; };
inline
void
AngleSet(int const i, double const a) {
fAngle[i] = a; };
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif

View File

@@ -268,32 +268,30 @@ TTrack * TTrack::NullCreate(int dir)
trk2->fRadius = 20.0; // promień, aby się dodawało do tabelki prędkości i liczyło trk2->fRadius = 20.0; // promień, aby się dodawało do tabelki prędkości i liczyło
// narastająco // narastająco
trk2->Init(); // utworzenie segmentu trk2->Init(); // utworzenie segmentu
trk->pMyNode->asName = pMyNode->asName + ":loopstart";
trk2->pMyNode->asName = pMyNode->asName + ":loopfinish";
switch (dir) switch (dir)
{ //łączenie z nowym torem { //łączenie z nowym torem
case 0: case 0:
p1 = Segment->FastGetPoint_0(); p1 = Segment->FastGetPoint_0();
cv1 = -20.0 * Normalize(Segment->GetDirection1()); // pierwszy wektor kontrolny cv1 = -20.0 * Normalize(Segment->GetDirection1()); // pierwszy wektor kontrolny
p2 = p1 + cv1 + cv1; // 40m p2 = p1 + cv1 + cv1; // 40m
trk->Segment->Init(p1, p1 + cv1, p2 + vector3(-cv1.z, cv1.y, cv1.x), p2, 2, // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
-RadToDeg(r1), trk->Segment->Init(p1, p1 + cv1, p2 + vector3(-cv1.z, cv1.y, cv1.x), p2, 2, -RadToDeg(r1), 0.0);
0.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
ConnectPrevPrev(trk, 0); ConnectPrevPrev(trk, 0);
trk2->Segment->Init(p1, p1 + cv1, p2 + vector3(cv1.z, cv1.y, -cv1.x), p2, 2, // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
-RadToDeg(r1), trk2->Segment->Init(p1, p1 + cv1, p2 + vector3(cv1.z, cv1.y, -cv1.x), p2, 2, -RadToDeg(r1), 0.0);
0.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk2->iPrevDirection = 0; // zwrotnie do tego samego odcinka trk2->iPrevDirection = 0; // zwrotnie do tego samego odcinka
break; break;
case 1: case 1:
p1 = Segment->FastGetPoint_1(); p1 = Segment->FastGetPoint_1();
cv1 = -20.0 * Normalize(Segment->GetDirection2()); // pierwszy wektor kontrolny cv1 = -20.0 * Normalize(Segment->GetDirection2()); // pierwszy wektor kontrolny
p2 = p1 + cv1 + cv1; p2 = p1 + cv1 + cv1;
trk->Segment->Init(p1, p1 + cv1, p2 + vector3(-cv1.z, cv1.y, cv1.x), p2, 2, // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
RadToDeg(r2), trk->Segment->Init(p1, p1 + cv1, p2 + vector3(-cv1.z, cv1.y, cv1.x), p2, 2, RadToDeg(r2), 0.0);
0.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
ConnectNextPrev(trk, 0); ConnectNextPrev(trk, 0);
trk2->Segment->Init(p1, p1 + cv1, p2 + vector3(cv1.z, cv1.y, -cv1.x), p2, 2, // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
RadToDeg(r2), trk2->Segment->Init(p1, p1 + cv1, p2 + vector3(cv1.z, cv1.y, -cv1.x), p2, 2, RadToDeg(r2), 0.0);
0.0); // bo prosty, kontrolne wyliczane przy zmiennej przechyłce
trk2->iPrevDirection = 1; // zwrotnie do tego samego odcinka trk2->iPrevDirection = 1; // zwrotnie do tego samego odcinka
break; break;
} }
@@ -870,7 +868,7 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
} }
else { else {
if( evEventall1 == nullptr ) { if( evEventall1 == nullptr ) {
evEventall1 = NewEvent0; evEventall1 = NewEvent1;
asEventall1Name = ""; asEventall1Name = "";
iEvents |= 16; // sumaryczna informacja o eventach iEvents |= 16; // sumaryczna informacja o eventach
} }
@@ -888,7 +886,7 @@ bool TTrack::AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEv
} }
else { else {
if( evEventall2 == nullptr ) { if( evEventall2 == nullptr ) {
evEventall2 = NewEvent0; evEventall2 = NewEvent2;
asEventall2Name = ""; asEventall2Name = "";
iEvents |= 32; // sumaryczna informacja o eventach iEvents |= 32; // sumaryczna informacja o eventach
} }

20
Track.h
View File

@@ -77,7 +77,7 @@ class TSwitchExtension
struct struct
{ // zmienne dla skrzyżowania { // zmienne dla skrzyżowania
int iRoads; // ile dróg się spotyka? int iRoads; // ile dróg się spotyka?
vector3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze Math3D::vector3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze
// int iPoints; // liczba faktycznie użytych wierzchołków nawierzchni // int iPoints; // liczba faktycznie użytych wierzchołków nawierzchni
bool bPoints; // czy utworzone? bool bPoints; // czy utworzone?
}; };
@@ -90,7 +90,7 @@ class TSwitchExtension
TEvent *evPlus = nullptr, TEvent *evPlus = nullptr,
*evMinus = nullptr; // zdarzenia sygnalizacji rozprucia *evMinus = nullptr; // zdarzenia sygnalizacji rozprucia
float fVelocity = -1.0; // maksymalne ograniczenie prędkości (ustawianej eventem) float fVelocity = -1.0; // maksymalne ograniczenie prędkości (ustawianej eventem)
vector3 vTrans; // docelowa translacja przesuwnicy Math3D::vector3 vTrans; // docelowa translacja przesuwnicy
private: private:
}; };
@@ -197,14 +197,14 @@ public:
void ConnectPrevNext(TTrack *pNewPrev, int typ); void ConnectPrevNext(TTrack *pNewPrev, int typ);
void ConnectNextPrev(TTrack *pNewNext, int typ); void ConnectNextPrev(TTrack *pNewNext, int typ);
void ConnectNextNext(TTrack *pNewNext, int typ); void ConnectNextNext(TTrack *pNewNext, int typ);
inline double Length() { inline double Length() const {
return Segment->GetLength(); }; return Segment->GetLength(); };
inline std::shared_ptr<TSegment> CurrentSegment() { inline std::shared_ptr<TSegment> CurrentSegment() const {
return Segment; }; return Segment; };
inline TTrack * CurrentNext() { inline TTrack *CurrentNext() const {
return (trNext); }; return trNext; };
inline TTrack * CurrentPrev() { inline TTrack *CurrentPrev() const {
return (trPrev); }; return trPrev; };
TTrack * Neightbour(int s, double &d); TTrack * Neightbour(int s, double &d);
bool SetConnections(int i); bool SetConnections(int i);
bool Switch(int i, double t = -1.0, double d = -1.0); bool Switch(int i, double t = -1.0, double d = -1.0);
@@ -215,7 +215,7 @@ public:
SwitchExtension ? SwitchExtension ?
SwitchExtension->CurrentIndex : SwitchExtension->CurrentIndex :
-1); }; -1); };
void Load(cParser *parser, vector3 pOrigin, std::string name); void Load(cParser *parser, Math3D::vector3 pOrigin, std::string name);
bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2); bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2); bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus); bool AssignForcedEvents(TEvent *NewEventPlus, TEvent *NewEventMinus);
@@ -247,7 +247,7 @@ public:
m_material1 : m_material1 :
m_material2 ); }; m_material2 ); };
bool IsGroupable(); bool IsGroupable();
int TestPoint(vector3 *Point); int TestPoint( Math3D::vector3 *Point);
void MovedUp1(float const dh); void MovedUp1(float const dh);
std::string NameGet(); std::string NameGet();
void VelocitySet(float v); void VelocitySet(float v);

View File

@@ -71,19 +71,11 @@ TTrack * TTrackFollower::SetCurrentTrack(TTrack *pTrack, int end)
} }
break; break;
} }
if (!pTrack) if (!pTrack) {
{ // gdy nie ma toru w kierunku jazdy // gdy nie ma toru w kierunku jazdy tworzenie toru wykolejącego na przedłużeniu pCurrentTrack
pTrack = pCurrentTrack->NullCreate( pTrack = pCurrentTrack->NullCreate(end);
end); // tworzenie toru wykolejącego na przedłużeniu pCurrentTrack
if (!end) // jeśli dodana od strony zero, to zmiana kierunku if (!end) // jeśli dodana od strony zero, to zmiana kierunku
fDirection = -fDirection; // wtórna zmiana fDirection = -fDirection; // wtórna zmiana
// if (pTrack->iCategoryFlag&2)
//{//jeśli samochód, zepsuć na miejscu
// Owner->MoverParameters->V=0; //zatrzymać
// Owner->MoverParameters->Power=0; //ukraść silnik
// Owner->MoverParameters->AccS=0; //wchłonąć moc
// Global::iPause|=1; //zapauzowanie symulacji
//}
} }
else else
{ // najpierw +1, później -1, aby odcinek izolowany wspólny dla tych torów nie wykrył zera { // najpierw +1, później -1, aby odcinek izolowany wspólny dla tych torów nie wykrył zera

View File

@@ -28,8 +28,8 @@ class TTrackFollower
// zwrotnicy pod taborem) // zwrotnicy pod taborem)
public: public:
double fOffsetH = 0.0; // Ra: odległość środka osi od osi toru (dla samochodów) - użyć do wężykowania double fOffsetH = 0.0; // Ra: odległość środka osi od osi toru (dla samochodów) - użyć do wężykowania
vector3 pPosition; // współrzędne XYZ w układzie scenerii Math3D::vector3 pPosition; // współrzędne XYZ w układzie scenerii
vector3 vAngles; // x:przechyłka, y:pochylenie, z:kierunek w planie (w radianach) Math3D::vector3 vAngles; // x:przechyłka, y:pochylenie, z:kierunek w planie (w radianach)
TTrackFollower() = default; TTrackFollower() = default;
~TTrackFollower(); ~TTrackFollower();
TTrack * SetCurrentTrack(TTrack *pTrack, int end); TTrack * SetCurrentTrack(TTrack *pTrack, int end);
@@ -47,7 +47,7 @@ class TTrackFollower
{ {
return fDirection; return fDirection;
}; // zwrot na torze }; // zwrot na torze
inline double GetTranslation() inline double GetTranslation() const
{ {
return fCurrentDistance; return fCurrentDistance;
}; // ABu-030403 }; // ABu-030403

View File

@@ -1048,17 +1048,19 @@ bool TWorld::Update()
// this means at count > 20 simulation and render are going to desync. is that right? // this means at count > 20 simulation and render are going to desync. is that right?
// NOTE: experimentally changing this to prevent the desync. // NOTE: experimentally changing this to prevent the desync.
// TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps // TODO: test what happens if we hit more than 20 * 0.01 sec slices, i.e. less than 5 fps
Ground.Update(dt / updatecount, updatecount); // tu zrobić tylko coklatkową aktualizację przesunięć for( int updateidx = 0; updateidx < updatecount; ++updateidx ) {
Ground.Update( dt / updatecount, 1 ); // tu zrobić tylko coklatkową aktualizację przesunięć
}
// yB dodał przyspieszacz fizyki // yB dodał przyspieszacz fizyki
if( (true == DebugModeFlag) if( (true == DebugModeFlag)
&& (true == Global::bActive) // nie przyspieszać, gdy jedzie w tle :) && (true == Global::bActive) // nie przyspieszać, gdy jedzie w tle :)
&& ( glfwGetKey( window, GLFW_KEY_PAUSE ) == GLFW_PRESS ) ) { && ( glfwGetKey( window, GLFW_KEY_PAUSE ) == GLFW_PRESS ) ) {
Ground.Update( dt, updatecount ); Ground.Update( dt, 1 );
Ground.Update( dt, updatecount ); Ground.Update( dt, 1 );
Ground.Update( dt, updatecount ); Ground.Update( dt, 1 );
Ground.Update( dt, updatecount ); // 5 razy Ground.Update( dt, 1 ); // 5 razy
} }
// secondary fixed step simulation time routines // secondary fixed step simulation time routines

View File

@@ -95,4 +95,23 @@ bounding_box( VecType_ &Mincorner, VecType_ &Maxcorner, Iterator_ First, Iterato
Maxcorner = glm::max( Maxcorner, VecType_{ point } ); } ); Maxcorner = glm::max( Maxcorner, VecType_{ point } ); } );
} }
// finds point on specified segment closest to specified point in 3d space. returns: point on segment as value in range 0-1 where 0 = start and 1 = end of the segment
template <typename VecType_>
typename VecType_::value_type
nearest_segment_point( VecType_ const &Segmentstart, VecType_ const &Segmentend, VecType_ const &Point ) {
auto const v = Segmentend - Segmentstart;
auto const w = Point - Segmentstart;
auto const c1 = glm::dot( w, v );
if( c1 <= 0.0 ) {
return 0.0;
}
auto const c2 = glm::dot( v, v );
if( c2 <= c1 ) {
return 1.0;
}
return c1 / c2;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

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