mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
919 lines
34 KiB
C++
919 lines
34 KiB
C++
//---------------------------------------------------------------------------
|
|
|
|
#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++;
|
|
}
|
|
}
|
|
};
|
|
//---------------------------------------------------------------------------
|
|
|
|
|