build 170511. crossroad generation for vbo render path. partial unification of generation and render functions for tracks and ground nodes

This commit is contained in:
tmj-fstate
2017-05-12 00:10:40 +02:00
parent 6655011af7
commit 5544ed33e9
9 changed files with 1250 additions and 1529 deletions

View File

@@ -230,9 +230,7 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
if( fDist < 50.0 ) {
// old sceneries use trick of placing 'helper' semaphores underground, which can lead to vehicles running over them instead of stopping in front of them
// to account for it at short distances we redo distance calculation on 2d plane
fDist = glm::dot(
glm::vec3( v.x, 0.0, v.z ),
glm::vec3( dir->x, 0.0, dir->z ) );
fDist = glm::length( glm::vec3( v.x, 0.0, v.z ) );
}
}
}

View File

@@ -290,16 +290,13 @@ void TGroundNode::RaRenderVBO()
glDrawArrays(iType, iVboPtr, iNumVerts); // Narysuj naraz wszystkie trójkąty
}
#ifdef EU07_USE_OLD_RENDERCODE
void TGroundNode::RenderVBO() { // renderowanie obiektu z VBO - faza nieprzezroczystych
switch( iType ) { // obiekty renderowane niezależnie od odległości
case TP_SUBMODEL:
TSubModel::fSquareDist = 0;
#ifdef EU07_USE_OLD_RENDERCODE
return smTerrain->RenderDL();
#else
GfxRenderer.Render( smTerrain );
#endif
}
double distancesquared = SquareMagnitude( pCenter - Global::pCameraPosition ) / Global::ZoomFactor;
@@ -334,15 +331,9 @@ void TGroundNode::RenderVBO() { // renderowanie obiektu z VBO - faza nieprzezroc
if( linealpha > 255 )
linealpha = 255;
float r, g, b;
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = floor( Diffuse[ 0 ] * Global::ambientDayLight[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::ambientDayLight[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::ambientDayLight[ 2 ] );
#else
r = floor( Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] );
#endif
glColor4ub( r, g, b, linealpha ); // przezroczystosc dalekiej linii
GfxRenderer.Bind( 0 );
@@ -436,6 +427,8 @@ void TGroundNode::RenderAlphaVBO()
#endif
}
#endif
void TGroundNode::Compile(bool many)
{ // tworzenie skompilowanej listy w wyświetlaniu DL
if (!many)
@@ -451,49 +444,28 @@ void TGroundNode::Compile(bool many)
}
if ((iType == GL_LINES) || (iType == GL_LINE_STRIP) || (iType == GL_LINE_LOOP))
{
#ifdef USE_VERTEX_ARRAYS
glVertexPointer(3, GL_DOUBLE, sizeof(vector3), &Points[0].x);
glDrawArrays(iType, 0, iNumPts);
#else
glBegin(iType);
for (int i = 0; i < iNumPts; i++)
glVertex3dv(&Points[i].x);
glEnd();
#endif
}
else if (iType == GL_TRIANGLE_STRIP || iType == GL_TRIANGLE_FAN || iType == GL_TRIANGLES)
{ // jak nie linie, to trójkąty
TGroundNode *tri = this;
do
{ // pętla po obiektach w grupie w celu połączenia siatek
#ifdef USE_VERTEX_ARRAYS
glVertexPointer(3, GL_DOUBLE, sizeof(TGroundVertex), &tri->Vertices[0].Point.x);
glNormalPointer(GL_DOUBLE, sizeof(TGroundVertex), &tri->Vertices[0].Normal.x);
glTexCoordPointer(2, GL_FLOAT, sizeof(TGroundVertex), &tri->Vertices[0].tu);
#endif
// TODO: eliminate these calls, they're duplicated by setup part in the unified render function
glColor3ub(tri->Diffuse[0], tri->Diffuse[1], tri->Diffuse[2]);
GfxRenderer.Bind(Global::bWireFrame ? 0 : tri->TextureID);
#ifdef USE_VERTEX_ARRAYS
glDrawArrays(Global::bWireFrame ? GL_LINE_LOOP : tri->iType, 0, tri->iNumVerts);
#else
glBegin(Global::bWireFrame ? GL_LINE_LOOP : tri->iType);
for (int i = 0; i < tri->iNumVerts; i++)
{
glNormal3d(tri->Vertices[i].Normal.x, tri->Vertices[i].Normal.y,
tri->Vertices[i].Normal.z);
glNormal3dv(&tri->Vertices[i].Normal.x);
glTexCoord2f(tri->Vertices[i].tu, tri->Vertices[i].tv);
glVertex3dv(&tri->Vertices[i].Point.x);
};
glEnd();
#endif
/*
if (tri->pTriGroup) //jeśli z grupy
{tri=tri->pNext2; //następny w sektorze
while (tri?!tri->pTriGroup:false) tri=tri->pNext2; //szukamy kolejnego należącego do
grupy
}
else
*/
tri = NULL; // a jak nie, to koniec
} while (tri);
}
@@ -552,17 +524,14 @@ void TGroundNode::RenderHidden()
}
};
#ifdef EU07_USE_OLD_RENDERCODE
void TGroundNode::RenderDL()
{ // wyświetlanie obiektu przez Display List
switch (iType)
{ // obiekty renderowane niezależnie od odległości
case TP_SUBMODEL:
TSubModel::fSquareDist = 0;
#ifdef EU07_USE_OLD_RENDERCODE
return smTerrain->RenderDL();
#else
GfxRenderer.Render( smTerrain );
#endif
}
double distancesquared = SquareMagnitude(pCenter - Global::pCameraPosition) / Global::ZoomFactor;
@@ -605,15 +574,9 @@ void TGroundNode::RenderDL()
if( linealpha > 255 )
linealpha = 255;
float r, g, b;
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = floor( Diffuse[ 0 ] * Global::ambientDayLight[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::ambientDayLight[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::ambientDayLight[ 2 ] );
#else
r = floor( Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ); // w zaleznosci od koloru swiatla
g = floor( Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] );
b = floor( Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] );
#endif
glColor4ub( r, g, b, linealpha ); // przezroczystosc dalekiej linii
GfxRenderer.Bind( 0 );
@@ -689,15 +652,9 @@ void TGroundNode::RenderAlphaDL()
float linealpha = 255000 * fLineThickness / ( distancesquared + 1.0 );
if (linealpha > 255)
linealpha = 255;
#ifdef EU07_USE_OLD_LIGHTING_MODEL
r = Diffuse[ 0 ] * Global::ambientDayLight[ 0 ]; // w zaleznosci od koloru swiatla
g = Diffuse[ 1 ] * Global::ambientDayLight[ 1 ];
b = Diffuse[ 2 ] * Global::ambientDayLight[ 2 ];
#else
float r = Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ]; // w zaleznosci od koloru swiatla
float g = Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ];
float b = Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ];
#endif
glColor4ub( r, g, b, linealpha ); // przezroczystosc dalekiej linii
GfxRenderer.Bind( 0 );
@@ -720,6 +677,7 @@ void TGroundNode::RenderAlphaDL()
}
#endif
}
#endif
//------------------------------------------------------------------------------
//------------------ Podstawowy pojemnik terenu - sektor -----------------------
@@ -1093,8 +1051,7 @@ void TSubRect::LoadNodes()
case GL_LINE_STRIP:
case GL_LINE_LOOP:
n->iVboPtr = m_nVertexCount; // nowy początek
m_nVertexCount +=
n->iNumPts; // miejsce w tablicach normalnych i teksturowania się zmarnuje...
m_nVertexCount += n->iNumPts; // miejsce w tablicach normalnych i teksturowania się zmarnuje...
break;
case TP_TRACK:
n->iVboPtr = m_nVertexCount; // nowy początek
@@ -1180,10 +1137,10 @@ void TSubRect::RenderDL()
{ // renderowanie nieprzezroczystych (DL)
TGroundNode *node;
RaAnimate(); // przeliczenia animacji torów w sektorze
for (node = nRender; node; node = node->nNext3)
node->RenderDL(); // nieprzezroczyste obiekty (oprócz pojazdów)
for( node = nRender; node; node = node->nNext3 )
GfxRenderer.Render( node ); // nieprzezroczyste obiekty (oprócz pojazdów)
for (node = nRenderMixed; node; node = node->nNext3)
node->RenderDL(); // nieprzezroczyste z mieszanych modeli
GfxRenderer.Render( node ); // nieprzezroczyste z mieszanych modeli
for (int j = 0; j < iTracks; ++j)
tTracks[j]->RenderDyn(); // nieprzezroczyste fragmenty pojazdów na torach
#ifdef EU07_SCENERY_EDITOR
@@ -1237,13 +1194,10 @@ void TSubRect::RenderDL()
void TSubRect::RenderAlphaDL()
{ // renderowanie przezroczystych modeli oraz pojazdów (DL)
TGroundNode *node;
for (node = nRenderMixed; node; node = node->nNext3)
node->RenderAlphaDL(); // przezroczyste z mieszanych modeli
for (node = nRenderAlpha; node; node = node->nNext3)
node->RenderAlphaDL(); // przezroczyste modele
// for (node=tmp->nRender;node;node=node->nNext3)
// if (node->iType==TP_TRACK)
// node->pTrack->RenderAlpha(); //przezroczyste fragmenty pojazdów na torach
for( node = nRenderMixed; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // przezroczyste z mieszanych modeli
for( node = nRenderAlpha; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // przezroczyste modele
for (int j = 0; j < iTracks; ++j)
tTracks[j]->RenderDynAlpha(); // przezroczyste fragmenty pojazdów na torach
};
@@ -1255,15 +1209,15 @@ void TSubRect::RenderVBO()
LoadNodes(); // czemu tutaj?
if (StartVBO())
{
for (node = nRenderRect; node; node = node->nNext3)
if (node->iVboPtr >= 0)
node->RenderVBO(); // nieprzezroczyste obiekty terenu
for( node = nRenderRect; node; node = node->nNext3 )
if( node->iVboPtr >= 0 )
GfxRenderer.Render( node ); // nieprzezroczyste obiekty terenu
EndVBO();
}
for (node = nRender; node; node = node->nNext3)
node->RenderVBO(); // nieprzezroczyste obiekty (oprócz pojazdów)
for( node = nRender; node; node = node->nNext3 )
GfxRenderer.Render( node ); // nieprzezroczyste obiekty (oprócz pojazdów)
for (node = nRenderMixed; node; node = node->nNext3)
node->RenderVBO(); // nieprzezroczyste z mieszanych modeli
GfxRenderer.Render( node ); // nieprzezroczyste z mieszanych modeli
for (int j = 0; j < iTracks; ++j)
tTracks[j]->RenderDyn(); // nieprzezroczyste fragmenty pojazdów na torach
#ifdef EU07_SCENERY_EDITOR
@@ -1279,13 +1233,10 @@ void TSubRect::RenderVBO()
void TSubRect::RenderAlphaVBO()
{ // renderowanie przezroczystych modeli oraz pojazdów (VBO)
TGroundNode *node;
for (node = nRenderMixed; node; node = node->nNext3)
node->RenderAlphaVBO(); // przezroczyste z mieszanych modeli
for (node = nRenderAlpha; node; node = node->nNext3)
node->RenderAlphaVBO(); // przezroczyste modele
// for (node=tmp->nRender;node;node=node->nNext3)
// if (node->iType==TP_TRACK)
// node->pTrack->RenderAlpha(); //przezroczyste fragmenty pojazdów na torach
for( node = nRenderMixed; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // przezroczyste z mieszanych modeli
for( node = nRenderAlpha; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // przezroczyste modele
for (int j = 0; j < iTracks; ++j)
tTracks[j]->RenderDynAlpha(); // przezroczyste fragmenty pojazdów na torach
};
@@ -1300,8 +1251,6 @@ void TSubRect::RenderSounds()
//---------------------------------------------------------------------------
int TGroundRect::iFrameNumber = 0; // licznik wyświetlanych klatek
//TGroundRect::TGroundRect( float3 const &Position, float const Radius = 1000.0f * M_SQRT2 ) :
TGroundRect::~TGroundRect()
{
SafeDeleteArray(pSubRects);
@@ -1343,50 +1292,12 @@ void TGroundRect::RenderDL()
node->Compile(true);
glEndList();
}
nRender->RenderDL(); // nieprzezroczyste trójkąty kwadratu kilometrowego
GfxRenderer.Render( nRender ); // nieprzezroczyste trójkąty kwadratu kilometrowego
}
if (nRootMesh)
nRootMesh->RenderDL();
if( nRootMesh )
GfxRenderer.Render( nRootMesh );
iLastDisplay = iFrameNumber; // drugi raz nie potrzeba
}
/*
float width = 500.0f;
float height = 50.0f;
float3 vTopLeftFront( m_area.center.x - width, m_area.center.y + height, m_area.center.z + width );
float3 vTopLeftBack( m_area.center.x - width, m_area.center.y + height, m_area.center.z - width );
float3 vTopRightBack( m_area.center.x + width, m_area.center.y + height, m_area.center.z - width );
float3 vTopRightFront( m_area.center.x + width, m_area.center.y + height, m_area.center.z + width );
float3 vBottom_LeftFront( m_area.center.x - width, m_area.center.y - height, m_area.center.z + width );
float3 vBottom_LeftBack( m_area.center.x - width, m_area.center.y - height, m_area.center.z - width );
float3 vBottomRightBack( m_area.center.x + width, m_area.center.y - height, m_area.center.z - width );
float3 vBottomRightFront( m_area.center.x + width, m_area.center.y - height, m_area.center.z + width );
glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D );
glColor3ub( 0, 255, 255 );
glBegin( GL_LINE_LOOP );
glVertex3fv( &vTopLeftFront.x );
glVertex3fv( &vTopLeftBack.x );
glVertex3fv( &vTopRightBack.x );
glVertex3fv( &vTopRightFront.x );
glEnd();
glBegin( GL_LINE_LOOP );
glVertex3fv( &vBottom_LeftFront.x );
glVertex3fv( &vBottom_LeftBack.x );
glVertex3fv( &vBottomRightBack.x );
glVertex3fv( &vBottomRightFront.x );
glEnd();
glBegin( GL_LINES );
glVertex3fv( &vTopLeftFront.x ); glVertex3fv( &vBottom_LeftFront.x );
glVertex3fv( &vTopLeftBack.x ); glVertex3fv( &vBottom_LeftBack.x );
glVertex3fv( &vTopRightBack.x ); glVertex3fv( &vBottomRightBack.x );
glVertex3fv( &vTopRightFront.x ); glVertex3fv( &vBottomRightFront.x );
glEnd();
glColor3ub( 255, 255, 255 );
glEnable( GL_TEXTURE_2D );
glEnable( GL_LIGHTING );
*/
};
void TGroundRect::RenderVBO()
@@ -1410,46 +1321,8 @@ void TGroundRect::RenderVBO()
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void TGround::MoveGroundNode(vector3 pPosition)
{ // Ra: to wymaga gruntownej reformy
/*
TGroundNode *Current;
for (Current=RootNode;Current!=NULL;Current=Current->Next)
Current->MoveMe(pPosition);
TGroundRect *Rectx=new TGroundRect; //kwadrat kilometrowy
for(int i=0;i<iNumRects;i++)
for(int j=0;j<iNumRects;j++)
Rects[i][j]=*Rectx; //kopiowanie zawartości do każdego kwadratu
delete Rectx;
for (Current=RootNode;Current!=NULL;Current=Current->Next)
{//rozłożenie obiektów na mapie
if (Current->iType!=TP_DYNAMIC)
{//pojazdów to w ogóle nie dotyczy
if ((Current->iType!=GL_TRIANGLES)&&(Current->iType!=GL_TRIANGLE_STRIP)?true //~czy trójkąt?
:(Current->iFlags&0x20)?true //~czy teksturę ma nieprzezroczystą?
//:(Current->iNumVerts!=3)?true //~czy tylko jeden trójkąt?
:(Current->fSquareMinRadius!=0.0)?true //~czy widoczny z bliska?
:(Current->fSquareRadius<=90000.0)) //~czy widoczny z daleka?
GetSubRect(Current->pCenter.x,Current->pCenter.z)->AddNode(Current);
else //dodajemy do kwadratu kilometrowego
GetRect(Current->pCenter.x,Current->pCenter.z)->AddNode(Current);
}
}
for (Current=RootDynamic;Current!=NULL;Current=Current->Next)
{
Current->pCenter+=pPosition;
Current->DynamicObject->UpdatePos();
}
for (Current=RootDynamic;Current!=NULL;Current=Current->Next)
Current->DynamicObject->MoverParameters->Physic_ReActivation();
*/
}
std::vector<TGroundVertex> TempVerts;
/*
TGroundVertex TempVerts[ 10000 ]; // tu wczytywane s¹ trójk¹ty
*/
BYTE TempConnectionType[ 200 ]; // Ra: sprzêgi w sk³adzie; ujemne, gdy odwrotnie
TGround::TGround()
@@ -4856,8 +4729,8 @@ bool TGround::RenderAlphaDL(vector3 pPosition)
for (i = iRendered - 1; i >= 0; --i) // od najdalszych
{ // przezroczyste trójkąty w oddzielnym cyklu przed modelami
tmp = pRendered[i];
for (node = tmp->nRenderRectAlpha; node; node = node->nNext3)
node->RenderAlphaDL(); // przezroczyste modele
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // przezroczyste modele
}
for (i = iRendered - 1; i >= 0; --i) // od najdalszych
{ // renderowanie przezroczystych modeli oraz pojazdów
@@ -4867,8 +4740,8 @@ bool TGround::RenderAlphaDL(vector3 pPosition)
for (i = iRendered - 1; i >= 0; --i) // od najdalszych
{ // druty na końcu, żeby się nie robiły białe plamy na tle lasu
tmp = pRendered[i];
for (node = tmp->nRenderWires; node; node = node->nNext3)
node->RenderAlphaDL(); // druty
for( node = tmp->nRenderWires; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // druty
}
return true;
}
@@ -4954,9 +4827,9 @@ bool TGround::RenderAlphaVBO(vector3 pPosition)
tmp->LoadNodes(); // ewentualne tworzenie siatek
if (tmp->StartVBO())
{
for (node = tmp->nRenderRectAlpha; node; node = node->nNext3)
if (node->iVboPtr >= 0)
node->RenderAlphaVBO(); // nieprzezroczyste obiekty terenu
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 )
if( node->iVboPtr >= 0 )
GfxRenderer.Render_Alpha( node ); // nieprzezroczyste obiekty terenu
tmp->EndVBO();
}
}
@@ -4968,8 +4841,8 @@ bool TGround::RenderAlphaVBO(vector3 pPosition)
tmp = pRendered[i];
if (tmp->StartVBO())
{
for (node = tmp->nRenderWires; node; node = node->nNext3)
node->RenderAlphaVBO(); // przezroczyste modele
for( node = tmp->nRenderWires; node; node = node->nNext3 )
GfxRenderer.Render_Alpha( node ); // przezroczyste modele
tmp->EndVBO();
}
}

View File

@@ -101,8 +101,11 @@ class TSubRect; // sektor (aktualnie 200m×200m, ale może być zmieniony)
class TGroundNode : public Resource
{ // obiekt scenerii
private:
public:
friend class opengl_renderer;
private:
public:
TGroundNodeType iType; // typ obiektu
union
{ // Ra: wskażniki zależne od typu - zrobić klasy dziedziczone zamiast
@@ -130,12 +133,7 @@ class TGroundNode : public Resource
};
vector3 pCenter; // współrzędne środka do przydzielenia sektora
union
{
// double fAngle; //kąt obrotu dla modelu
double fLineThickness; // McZapkie-120702: grubosc linii
// int Status; //McZapkie-170303: status dzwieku
};
double fLineThickness; // McZapkie-120702: grubosc linii
double fSquareRadius; // kwadrat widoczności do
double fSquareMinRadius; // kwadrat widoczności od
// TGroundNode *nMeshGroup; //Ra: obiekt grupujący trójkąty w TSubRect dla tekstury
@@ -174,12 +172,8 @@ class TGroundNode : public Resource
void Release();
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
void RenderDL(); // renderowanie nieprzezroczystych w Display Lists
void RenderAlphaDL(); // renderowanie przezroczystych w Display Lists
// (McZapkie-131202)
void RaRenderVBO(); // renderowanie (nieprzezroczystych) ze wspólnego VBO
void RenderVBO(); // renderowanie nieprzezroczystych z własnego VBO
void RenderAlphaVBO(); // renderowanie przezroczystych z (własnego) VBO
};
@@ -313,9 +307,6 @@ class TGround
public:
bool bDynamicRemove = false; // czy uruchomić procedurę usuwania pojazdów
TDynamicObject *LastDyn = nullptr; // ABu: paskudnie, ale na bardzo szybko moze jakos przejdzie...
// TTrain *pTrain;
// double fVDozwolona;
// bool bTrabil;
TGround();
~TGround();
@@ -329,7 +320,6 @@ class TGround
TTrack * FindTrack(vector3 Point, int &iConnection, TGroundNode *Exclude);
TTraction * FindTraction(vector3 *Point, int &iConnection, TGroundNode *Exclude);
TTraction * TractionNearestFind(vector3 &p, int dir, TGroundNode *n);
// TGroundNode* CreateGroundNode();
TGroundNode * AddGroundNode(cParser *parser);
bool AddGroundNode(double x, double z, TGroundNode *Node)
{
@@ -342,11 +332,6 @@ class TGround
else
return false;
};
// bool Include(TQueryParserComp *Parser);
// TGroundNode* GetVisible(AnsiString asName);
TGroundNode * GetNode(std::string asName);
bool AddDynamic(TGroundNode *Node);
void MoveGroundNode(vector3 pPosition);
void UpdatePhys(double dt, int iter); // aktualizacja fizyki stałym krokiem
bool Update(double dt, int iter); // aktualizacja przesunięć zgodna z FPS
void Update_Lights(); // updates scene lights array
@@ -358,23 +343,6 @@ class TGround
bool RenderVBO(vector3 pPosition);
bool RenderAlphaVBO(vector3 pPosition);
bool CheckQuery();
// GetRect(double x, double z) { return
// &(Rects[int(x/fSubRectSize+fHalfNumRects)][int(z/fSubRectSize+fHalfNumRects)]); };
/*
int GetRowFromZ(double z) { return (z/fRectSize+fHalfNumRects); };
int GetColFromX(double x) { return (x/fRectSize+fHalfNumRects); };
int GetSubRowFromZ(double z) { return (z/fSubRectSize+fHalfNumSubRects); };
int GetSubColFromX(double x) { return (x/fSubRectSize+fHalfNumSubRects); };
*/
/*
inline TGroundNode* FindGroundNode(const AnsiString &asNameToFind )
{
if (RootNode)
return (RootNode->Find( asNameToFind ));
else
return NULL;
}
*/
TGroundNode * DynamicFindAny(std::string asNameToFind);
TGroundNode * DynamicFind(std::string asNameToFind);
void DynamicList(bool all = false);
@@ -419,7 +387,6 @@ class TGround
void WyslijNamiary(TGroundNode *t);
void WyslijParam(int nr, int fl);
void WyslijUszkodzenia(const std::string &t, char fl);
void WyslijPojazdy(int nr); // -> skladanie wielu pojazdow
void WyslijObsadzone(); // -> skladanie wielu pojazdow
void RadioStop(vector3 pPosition);
TDynamicObject * DynamicNearest(vector3 pPosition, double distance = 20.0,

View File

@@ -19,12 +19,6 @@ http://mozilla.org/MPL/2.0/.
// 101206 Ra: trapezoidalne drogi
// 110806 Ra: odwrócone mapowanie wzdłuż - Point1 == 1.0
float Interpolate( float const First, float const Second, float const Factor ) {
return ( First * ( 1.0f - Factor ) ) + ( Second * Factor );
}
std::string Where(vector3 p)
{ // zamiana współrzędnych na tekst, używana w błędach
return std::to_string(p.x) + " " + std::to_string(p.y) + " " + std::to_string(p.z);
@@ -122,15 +116,14 @@ bool TSegment::Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointI
// MessageBox(0,"Length<=0","TSegment::Init",MB_OK);
return false; // zerowe nie mogą być
}
fStoop = atan2((Point2.y - Point1.y),
fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
fStoop = std::atan2((Point2.y - Point1.y), fLength); // pochylenie toru prostego, żeby nie liczyć wielokrotnie
SafeDeleteArray(fTsBuffer);
if( ( bCurve ) && ( fStep > 0 ) ) {
if( fStep > 0 ) { // Ra: prosty dostanie podział, jak ma różną przechyłkę na końcach
double s = 0;
int i = 0;
iSegCount = ceil( fLength / fStep ); // potrzebne do VBO
iSegCount = static_cast<int>( std::ceil( fLength / fStep )); // potrzebne do VBO
// fStep=fLength/(double)(iSegCount-1); //wyrównanie podziału
fTsBuffer = new double[ iSegCount + 1 ];
fTsBuffer[ 0 ] = 0; /* TODO : fix fTsBuffer */
@@ -324,408 +317,213 @@ vector3 TSegment::FastGetPoint(double t)
return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2));
}
void TSegment::RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength,
int iSkip, int iQualityFactor, vector3 **p, bool bRender)
void TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, bool Onlypositions, vector3 **p, bool bRender)
{ // generowanie trójkątów dla odcinka trajektorii ruchu
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
// podany jest przekrój końcowy
// podsypka toru jest robiona za pomocą 6 punktów, szyna 12, drogi i rzeki na 3+2+3
if (iQualityFactor < 1)
iQualityFactor = 1; // co który segment ma być uwzględniony
if( !fTsBuffer )
return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
double s, step, fOffset, tv1, tv2, t;
int i, j;
bool trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
iNumShapePoints = abs(iNumShapePoints);
if (bCurve)
{
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
step = fStep * iQualityFactor;
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
i = iSkip; // domyślnie 0
if (!fTsBuffer)
return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
if (i > iSegCount)
return; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
t = fTsBuffer[i]; // tabela watości t dla segmentów
fOffset = 0.1 / fLength; // pierwsze 10cm
pos1 = FastGetPoint(t); // wektor początku segmentu
dir = FastGetDirection(t, fOffset); // wektor kierunku
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //wektor poprzeczny
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
m2 = s / fLength;
jmm2 = 1.0 - m2;
while (s < fLength)
{
// step=SquareMagnitude(Global::GetCameraPosition()+pos);
i += iQualityFactor; // kolejny punkt łamanej
s += step; // końcowa pozycja segmentu [m]
m1 = m2;
jmm1 = jmm2; // stara pozycja
m2 = s / fLength;
jmm2 = 1.0 - m2; // nowa pozycja
if (s > fLength - 0.5) // Ra: -0.5 żeby nie robiło cieniasa na końcu
{ // gdy przekroczyliśmy koniec - stąd dziury w torach...
step -= (s - fLength); // jeszcze do wyliczenia mapowania potrzebny
s = fLength;
i = iSegCount; // 20/5 ma dawać 4
m2 = 1.0;
jmm2 = 0.0;
}
while (tv1 < 0.0)
tv1 += 1.0; // przestawienie mapowania
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
t = fTsBuffer[i]; // szybsze od GetTFromS(s);
pos2 = FastGetPoint(t);
dir = FastGetDirection(t, fOffset); // nowy wektor kierunku
// parallel2=CrossProduct(dir,vector3(0,1,0)); //wektor poprzeczny
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
glBegin(GL_TRIANGLE_STRIP);
if (trapez)
for (j = 0; j < iNumShapePoints; j++)
{
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
parallel1;
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
pt = parallel1 *
(jmm1 * ShapePoints[j].x + m1 * ShapePoints[j + iNumShapePoints].x) +
pos1;
pt.y += jmm1 * ShapePoints[j].y + m1 * ShapePoints[j + iNumShapePoints].y;
if (bRender)
{ // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale
// potrzebować punktów
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(
jmm1 * ShapePoints[j].z + m1 * ShapePoints[j + iNumShapePoints].z, tv1);
glVertex3f(pt.x, pt.y, pt.z); // pt nie mamy gdzie zapamiętać?
}
// BUG: things blow up badly in the following part in 64bit version on baltyk.scn
// TODO: sort this mess out when the time comes to reorganize spline generation
if( p ) // jeśli jest wskaźnik do tablicy
if (*p)
if (!j) // to dla pierwszego punktu
{
*(*p) = pt;
(*p)++;
} // zapamiętanie brzegu jezdni
// dla trapezu drugi koniec ma inne współrzędne
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
parallel2;
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
pt = parallel2 *
(jmm2 * ShapePoints[j].x + m2 * ShapePoints[j + iNumShapePoints].x) +
pos2;
pt.y += jmm2 * ShapePoints[j].y + m2 * ShapePoints[j + iNumShapePoints].y;
if (bRender)
{ // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale
// potrzebować punktów
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(
jmm2 * ShapePoints[j].z + m2 * ShapePoints[j + iNumShapePoints].z, tv2);
glVertex3f(pt.x, pt.y, pt.z);
}
if (p) // jeśli jest wskaźnik do tablicy
if (*p)
if (!j) // to dla pierwszego punktu
if (i == iSegCount)
{
*(*p) = pt;
(*p)++;
} // zapamiętanie brzegu jezdni
}
else
for (j = 0; j < iNumShapePoints; j++)
{ //łuk z jednym profilem
norm = ShapePoints[j].n.x * parallel1;
norm.y += ShapePoints[j].n.y;
pt = parallel1 * ShapePoints[j].x + pos1;
pt.y += ShapePoints[j].y;
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(ShapePoints[j].z, tv1);
glVertex3f(pt.x, pt.y, pt.z); // punkt na początku odcinka
norm = ShapePoints[j].n.x * parallel2;
norm.y += ShapePoints[j].n.y;
pt = parallel2 * ShapePoints[j].x + pos2;
pt.y += ShapePoints[j].y;
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(ShapePoints[j].z, tv2);
glVertex3f(pt.x, pt.y, pt.z); // punkt na końcu odcinka
}
glEnd();
pos1 = pos2;
parallel1 = parallel2;
tv1 = tv2;
double s, step, fOffset, tv1, tv2, t, fEnd;
bool const trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
iNumShapePoints = std::abs( iNumShapePoints );
fTextureLength *= Texturescale;
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
step = fStep;
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
int i = iSkip; // domyślnie 0
t = fTsBuffer[ i ]; // tabela wattości t dla segmentów
// BUG: length of spline can be 0, we should skip geometry generation for such cases
fOffset = 0.1 / fLength; // pierwsze 10cm
pos1 = FastGetPoint( t ); // wektor początku segmentu
dir = FastGetDirection( t, fOffset ); // wektor kierunku
parallel1 = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
if( iEnd == 0 )
iEnd = iSegCount;
fEnd = fLength * double( iEnd ) / double( iSegCount );
m2 = s / fEnd;
jmm2 = 1.0 - m2;
while( i < iEnd ) {
++i; // kolejny punkt łamanej
s += step; // końcowa pozycja segmentu [m]
m1 = m2;
jmm1 = jmm2; // stara pozycja
m2 = s / fEnd;
jmm2 = 1.0 - m2; // nowa pozycja
if( i == iEnd ) { // gdy przekroczyliśmy koniec - stąd dziury w torach...
step -= ( s - fEnd ); // jeszcze do wyliczenia mapowania potrzebny
s = fEnd;
m2 = 1.0;
jmm2 = 0.0;
}
}
else
#ifdef EU07_USE_OLD_LIGHTING_MODEL
{ // gdy prosty, nie modyfikujemy wektora kierunkowego i poprzecznego
pos1 = FastGetPoint((fStep * iSkip) / fLength);
pos2 = FastGetPoint_1();
dir = GetDirection();
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0)));
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
glBegin(GL_TRIANGLE_STRIP);
if (trapez)
for (j = 0; j < iNumShapePoints; j++)
{
norm = ShapePoints[j].n.x * parallel1;
norm.y += ShapePoints[j].n.y;
pt = parallel1 * ShapePoints[j].x + pos1;
pt.y += ShapePoints[j].y;
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(ShapePoints[j].z, 0);
glVertex3f(pt.x, pt.y, pt.z);
// dla trapezu drugi koniec ma inne współrzędne względne
norm = ShapePoints[j + iNumShapePoints].n.x * parallel1;
norm.y += ShapePoints[j + iNumShapePoints].n.y;
pt = parallel1 * ShapePoints[j + iNumShapePoints].x + pos2; // odsunięcie
pt.y += ShapePoints[j + iNumShapePoints].y; // wysokość
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(ShapePoints[j + iNumShapePoints].z, fLength / fTextureLength);
glVertex3f(pt.x, pt.y, pt.z);
if( false == Onlypositions ) {
while( tv1 < 0.0 ) {
tv1 += 1.0;
}
else
for (j = 0; j < iNumShapePoints; j++)
{
norm = ShapePoints[j].n.x * parallel1;
norm.y += ShapePoints[j].n.y;
pt = parallel1 * ShapePoints[j].x + pos1;
pt.y += ShapePoints[j].y;
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(ShapePoints[j].z, 0);
glVertex3f(pt.x, pt.y, pt.z);
pt = parallel1 * ShapePoints[j].x + pos2;
pt.y += ShapePoints[j].y;
glNormal3f(norm.x, norm.y, norm.z);
glTexCoord2f(ShapePoints[j].z, fLength / fTextureLength);
glVertex3f(pt.x, pt.y, pt.z);
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
}
t = fTsBuffer[ i ]; // szybsze od GetTFromS(s);
pos2 = FastGetPoint( t );
dir = FastGetDirection( t, fOffset ); // nowy wektor kierunku
parallel2 = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
if( Output == nullptr ) {
// immediate mode
::glBegin( GL_TRIANGLE_STRIP );
}
if( trapez ) {
for( int j = 0; j < iNumShapePoints; ++j ) {
pt = parallel1 * ( jmm1 * ( ShapePoints[ j ].x - fOffsetX ) + m1 * ShapePoints[ j + iNumShapePoints ].x ) + pos1;
pt.y += jmm1 * ShapePoints[ j ].y + m1 * ShapePoints[ j + iNumShapePoints ].y;
if( false == Onlypositions ) {
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel1;
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
}
if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
if( Output == nullptr ) {
// immediate mode
if( false == Onlypositions ) {
::glNormal3f( norm.x, norm.y, norm.z );
::glTexCoord2f( (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv1 );
}
::glVertex3f( pt.x, pt.y, pt.z ); // pt nie mamy gdzie zapamiętać?
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
if( false == Onlypositions ) {
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->v = tv1;
}
++Output;
}
}
if( p ) // jeśli jest wskaźnik do tablicy
if( *p )
if( !j ) // to dla pierwszego punktu
{
*( *p ) = pt;
( *p )++;
} // zapamiętanie brzegu jezdni
// dla trapezu drugi koniec ma inne współrzędne
pt = parallel2 * ( jmm2 * ( ShapePoints[ j ].x - fOffsetX ) + m2 * ShapePoints[ j + iNumShapePoints ].x ) + pos2;
pt.y += jmm2 * ShapePoints[ j ].y + m2 * ShapePoints[ j + iNumShapePoints ].y;
if( false == Onlypositions ) {
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel2;
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
}
if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
if( Output == nullptr ) {
// immediate mode
if( false == Onlypositions ) {
::glNormal3f( norm.x, norm.y, norm.z );
::glTexCoord2f( (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv2 );
}
::glVertex3f( pt.x, pt.y, pt.z );
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
if( false == Onlypositions ) {
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->v = tv2;
}
++Output;
}
}
if( p ) // jeśli jest wskaźnik do tablicy
if( *p )
if( !j ) // to dla pierwszego punktu
if( i == iSegCount ) {
*( *p ) = pt;
( *p )++;
} // zapamiętanie brzegu jezdni
}
glEnd();
}
#else
{
Math3D::vector3 const pos0 = FastGetPoint( ( fStep * iSkip ) / fLength );
Math3D::vector3 const pos1 = FastGetPoint_1();
dir = GetDirection();
Math3D::vector3 const parallel = Normalize( vector3( -dir.z, 0.0, dir.x ) ); // wektor poprzeczny
Math3D::vector3 startnormal0, startnormal1, endnormal0, endnormal1;
Math3D::vector3 startvertex0, startvertex1, endvertex0, endvertex1;
float startuv0, startuv1, enduv0, enduv1;
for( j = 0; j < iNumShapePoints - 1; ++j ) {
startnormal0 = ShapePoints[ j ].n.x * parallel;
startnormal0.y += ShapePoints[ j ].n.y;
startvertex0 = parallel * ShapePoints[ j ].x + pos0;
startvertex0.y += ShapePoints[ j ].y;
startuv0 = ShapePoints[ j ].z;
startnormal1 = ShapePoints[ j + 1 ].n.x * parallel;
startnormal1.y += ShapePoints[ j + 1 ].n.y;
startvertex1 = parallel * ShapePoints[ j + 1 ].x + pos0;
startvertex1.y += ShapePoints[ j + 1 ].y;
startuv1 = ShapePoints[ j + 1 ].z;
if( trapez == false ) {
// single profile throughout
endnormal0 = startnormal0;
endvertex0 = startvertex0 + ( pos1 - pos0 );
enduv0 = startuv0;
endnormal1 = startnormal1;
endvertex1 = startvertex1 + ( pos1 - pos0 );
enduv1 = startuv1;
}
else {
// end profile is different
endnormal0 = ShapePoints[ j + iNumShapePoints ].n.x * parallel;
endnormal0.y += ShapePoints[ j + iNumShapePoints ].n.y;
endvertex0 = parallel * ShapePoints[ j + iNumShapePoints ].x + pos1; // odsunięcie
endvertex0.y += ShapePoints[ j + iNumShapePoints ].y; // wysokość
enduv0 = ShapePoints[ j + iNumShapePoints ].z;
endnormal1 = ShapePoints[ j + iNumShapePoints + 1 ].n.x * parallel;
endnormal1.y += ShapePoints[ j + iNumShapePoints + 1 ].n.y;
endvertex1 = parallel * ShapePoints[ j + iNumShapePoints + 1 ].x + pos1; // odsunięcie
endvertex1.y += ShapePoints[ j + iNumShapePoints + 1 ].y; // wysokość
enduv1 = ShapePoints[ j + iNumShapePoints + 1 ].z;
}
// now build strips, lerping from start to endpoint
step = 10.0; // arbitrary segment size for straights
float s = 0.0,
t = 0.0,
uv = 0.0;
glBegin( GL_TRIANGLE_STRIP );
while( s < fLength ) {
t = s / fLength;
uv = s / fTextureLength;
auto const normal1lerp = Interpolate( startnormal1, endnormal1, t );
glNormal3dv( &normal1lerp.x );
auto const uv1lerp = Interpolate( startuv1, enduv1, t );
glTexCoord2f( uv1lerp, uv );
auto const vertex1lerp = Interpolate( startvertex1, endvertex1, t );
glVertex3dv( &vertex1lerp.x );
auto const normal0lerp = Interpolate( startnormal0, endnormal0, t );
glNormal3dv( &normal0lerp.x );
auto const uv0lerp = Interpolate( startuv0, enduv0, t );
glTexCoord2f( uv0lerp, uv );
auto const vertex0lerp = Interpolate( startvertex0, endvertex0, t );
glVertex3dv( &vertex0lerp.x );
s += step;
}
// add ending vertex pair if needed
glNormal3dv( &endnormal1.x );
glTexCoord2f( enduv1, fLength / fTextureLength );
glVertex3dv( &endvertex1.x );
glNormal3dv( &endnormal0.x );
glTexCoord2f( enduv0, fLength / fTextureLength );
glVertex3dv( &endvertex0.x );
glEnd();
}
}
#endif
};
void TSegment::RenderSwitchRail(const vector6 *ShapePoints1, const vector6 *ShapePoints2,
int iNumShapePoints, double fTextureLength, int iSkip,
double fOffsetX)
{ // tworzenie siatki trójkątów dla iglicy
vector3 pos1, pos2, dir, parallel1, parallel2, pt;
double a1, a2, s, step, offset, tv1, tv2, t, t2step, oldt2;
int i, j;
if (bCurve)
{ // dla toru odchylonego
// t2= 0;
t2step = 1 / double(iSkip); // przesunięcie tekstury?
oldt2 = 1;
tv1 = 1.0;
step = fStep; // długść segmentu
s = 0;
i = 0;
t = fTsBuffer[i]; // wartość t krzywej Beziera dla początku
a1 = 0;
// step= fStep/fLength;
offset = 0.1 / fLength; // około 10cm w sensie parametru t
pos1 = FastGetPoint(t); // współrzędne dla parmatru t
// dir= GetDirection1();
dir = FastGetDirection(t, offset); // wektor wzdłużny
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //poprzeczny?
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
while (s < fLength && i < iSkip)
{
// step= SquareMagnitude(Global::GetCameraPosition()+pos);
// t2= oldt2+t2step;
i++;
s += step;
if (s > fLength)
{
step -= (s - fLength);
s = fLength;
}
while (tv1 < 0.0)
tv1 += 1.0;
tv2 = tv1 - step / fTextureLength;
t = fTsBuffer[i];
pos2 = FastGetPoint(t);
dir = FastGetDirection(t, offset);
// parallel2=Normalize(CrossProduct(dir,vector3(0,1,0)));
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
a2 = double(i) / (iSkip);
glBegin(GL_TRIANGLE_STRIP);
for (j = 0; j < iNumShapePoints; j++)
{ // po dwa punkty trapezu
pt = parallel1 *
(ShapePoints1[j].x * a1 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a1)) +
pos1;
pt.y += ShapePoints1[j].y * a1 + ShapePoints2[j].y * (1.0 - a1);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(ShapePoints1[j].z * a1 + ShapePoints2[j].z * (1.0 - a1), tv1);
glVertex3f(pt.x, pt.y, pt.z);
pt = parallel2 *
(ShapePoints1[j].x * a2 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a2)) +
pos2;
pt.y += ShapePoints1[j].y * a2 + ShapePoints2[j].y * (1.0 - a2);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(ShapePoints1[j].z * a2 + ShapePoints2[j].z * (1.0 - a2), tv2);
glVertex3f(pt.x, pt.y, pt.z);
for( int j = 0; j < iNumShapePoints; ++j ) {
//łuk z jednym profilem
pt = parallel1 * ( ShapePoints[ j ].x - fOffsetX ) + pos1;
pt.y += ShapePoints[ j ].y;
if( false == Onlypositions ) {
norm = ShapePoints[ j ].n.x * parallel1;
norm.y += ShapePoints[ j ].n.y;
}
if( Output == nullptr ) {
// immediate mode
if( false == Onlypositions ) {
::glNormal3f( norm.x, norm.y, norm.z );
::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv1 );
}
::glVertex3f( pt.x, pt.y, pt.z ); // punkt na początku odcinka
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
if( false == Onlypositions ) {
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv1;
}
++Output;
}
pt = parallel2 * ShapePoints[ j ].x + pos2;
pt.y += ShapePoints[ j ].y;
if( false == Onlypositions ) {
norm = ShapePoints[ j ].n.x * parallel2;
norm.y += ShapePoints[ j ].n.y;
}
if( Output == nullptr ) {
// immediate mode
if( false == Onlypositions ) {
::glNormal3f( norm.x, norm.y, norm.z );
::glTexCoord2f( ShapePoints[ j ].z / Texturescale, tv2 );
}
::glVertex3f( pt.x, pt.y, pt.z ); // punkt na końcu odcinka
}
else {
Output->x = pt.x;
Output->y = pt.y;
Output->z = pt.z;
if( false == Onlypositions ) {
Output->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv2;
}
++Output;
}
}
}
if( Output == nullptr ) {
// immediate mode
glEnd();
pos1 = pos2;
parallel1 = parallel2;
tv1 = tv2;
a1 = a2;
}
}
else
{ // dla toru prostego
tv1 = 1.0;
s = 0;
i = 0;
// pos1= FastGetPoint( (5*iSkip)/fLength );
pos1 = FastGetPoint_0();
dir = GetDirection();
// parallel1=CrossProduct(dir,vector3(0,1,0));
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
step = 5;
a1 = 0;
while (i < iSkip)
{
// step= SquareMagnitude(Global::GetCameraPosition()+pos);
i++;
s += step;
if (s > fLength)
{
step -= (s - fLength);
s = fLength;
}
while (tv1 < 0.0)
tv1 += 1.0;
tv2 = tv1 - step / fTextureLength;
t = s / fLength;
pos2 = FastGetPoint(t);
a2 = double(i) / (iSkip);
glBegin(GL_TRIANGLE_STRIP);
for (j = 0; j < iNumShapePoints; j++)
{
pt = parallel1 *
(ShapePoints1[j].x * a1 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a1)) +
pos1;
pt.y += ShapePoints1[j].y * a1 + ShapePoints2[j].y * (1.0 - a1);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f((ShapePoints1[j].z), tv1);
glVertex3f(pt.x, pt.y, pt.z);
pt = parallel1 *
(ShapePoints1[j].x * a2 + (ShapePoints2[j].x - fOffsetX) * (1.0 - a2)) +
pos2;
pt.y += ShapePoints1[j].y * a2 + ShapePoints2[j].y * (1.0 - a2);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(ShapePoints2[j].z, tv2);
glVertex3f(pt.x, pt.y, pt.z);
}
glEnd();
pos1 = pos2;
pos1 = pos2;
parallel1 = parallel2;
if( false == Onlypositions ) {
tv1 = tv2;
a1 = a2;
}
}
};
@@ -778,301 +576,4 @@ void TSegment::Render()
}
}
void TSegment::RaRenderLoft(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
double fTextureLength, int iSkip, int iEnd, double fOffsetX)
{ // generowanie trójkątów dla odcinka trajektorii ruchu
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
// podany jest przekrój końcowy
// podsypka toru jest robiona za pomocą 6 punktów, szyna 12, drogi i rzeki na 3+2+3
// na użytek VBO strip dla łuków jest tworzony wzdłuż
// dla skróconego odcinka (iEnd<iSegCount), ShapePoints dotyczy
// końców skróconych, a nie całości (to pod kątem iglic jest)
vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
double s, step, fOffset, tv1, tv2, t, fEnd;
int i, j;
bool trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
iNumShapePoints = abs(iNumShapePoints);
if (bCurve)
{
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
step = fStep;
tv1 = 1.0; // Ra: to by można było wyliczać dla odcinka, wyglądało by lepiej
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
i = iSkip; // domyślnie 0
t = fTsBuffer[i]; // tabela wattości t dla segmentów
// BUG: length of spline can be 0, we should skip geometry generation for such cases
fOffset = 0.1 / fLength; // pierwsze 10cm
pos1 = FastGetPoint(t); // wektor początku segmentu
dir = FastGetDirection(t, fOffset); // wektor kierunku
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //wektor prostopadły
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
if (iEnd == 0)
iEnd = iSegCount;
fEnd = fLength * double(iEnd) / double(iSegCount);
m2 = s / fEnd;
jmm2 = 1.0 - m2;
while (i < iEnd)
{
++i; // kolejny punkt łamanej
s += step; // końcowa pozycja segmentu [m]
m1 = m2;
jmm1 = jmm2; // stara pozycja
m2 = s / fEnd;
jmm2 = 1.0 - m2; // nowa pozycja
if (i == iEnd)
{ // gdy przekroczyliśmy koniec - stąd dziury w torach...
step -= (s - fEnd); // jeszcze do wyliczenia mapowania potrzebny
s = fEnd;
// i=iEnd; //20/5 ma dawać 4
m2 = 1.0;
jmm2 = 0.0;
}
while (tv1 < 0.0)
tv1 += 1.0;
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
t = fTsBuffer[i]; // szybsze od GetTFromS(s);
pos2 = FastGetPoint(t);
dir = FastGetDirection(t, fOffset); // nowy wektor kierunku
// parallel2=Normalize(CrossProduct(dir,vector3(0,1,0)));
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
if (trapez)
for (j = 0; j < iNumShapePoints; j++)
{ // współrzędne początku
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
parallel1;
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
pt = parallel1 * (jmm1 * (ShapePoints[j].x - fOffsetX) +
m1 * ShapePoints[j + iNumShapePoints].x) +
pos1;
pt.y += jmm1 * ShapePoints[j].y + m1 * ShapePoints[j + iNumShapePoints].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = jmm1 * ShapePoints[j].z + m1 * ShapePoints[j + iNumShapePoints].z;
Vert->v = tv1;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na początku odcinka
Vert++;
// dla trapezu drugi koniec ma inne współrzędne względne
norm = (jmm1 * ShapePoints[j].n.x + m1 * ShapePoints[j + iNumShapePoints].n.x) *
parallel2;
norm.y += jmm1 * ShapePoints[j].n.y + m1 * ShapePoints[j + iNumShapePoints].n.y;
pt = parallel2 * (jmm2 * (ShapePoints[j].x - fOffsetX) +
m2 * ShapePoints[j + iNumShapePoints].x) +
pos2;
pt.y += jmm2 * ShapePoints[j].y + m2 * ShapePoints[j + iNumShapePoints].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = jmm2 * ShapePoints[j].z + m2 * ShapePoints[j + iNumShapePoints].z;
Vert->v = tv2;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na końcu odcinka
Vert++;
}
else
for (j = 0; j < iNumShapePoints; j++)
{ // współrzędne początku
norm = ShapePoints[j].n.x * parallel1;
norm.y += ShapePoints[j].n.y;
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
pt.y += ShapePoints[j].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = ShapePoints[j].z;
Vert->v = tv1;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na początku odcinka
Vert++;
norm = ShapePoints[j].n.x * parallel2;
norm.y += ShapePoints[j].n.y;
pt = parallel2 * ShapePoints[j].x + pos2;
pt.y += ShapePoints[j].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = ShapePoints[j].z;
Vert->v = tv2;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na końcu odcinka
Vert++;
}
pos1 = pos2;
parallel1 = parallel2;
tv1 = tv2;
}
}
else
{ // gdy prosty
pos1 = FastGetPoint((fStep * iSkip) / fLength);
pos2 = FastGetPoint_1();
dir = GetDirection();
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0)));
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
if (trapez)
for (j = 0; j < iNumShapePoints; j++)
{
norm = ShapePoints[j].n.x * parallel1;
norm.y += ShapePoints[j].n.y;
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
pt.y += ShapePoints[j].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = ShapePoints[j].z;
Vert->v = 0;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na początku odcinka
Vert++;
// dla trapezu drugi koniec ma inne współrzędne
norm = ShapePoints[j + iNumShapePoints].n.x * parallel1;
norm.y += ShapePoints[j + iNumShapePoints].n.y;
pt = parallel1 * (ShapePoints[j + iNumShapePoints].x - fOffsetX) +
pos2; // odsunięcie
pt.y += ShapePoints[j + iNumShapePoints].y; // wysokość
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = ShapePoints[j + iNumShapePoints].z;
Vert->v = fLength / fTextureLength;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na końcu odcinka
Vert++;
}
else
for (j = 0; j < iNumShapePoints; j++)
{
norm = ShapePoints[j].n.x * parallel1;
norm.y += ShapePoints[j].n.y;
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
pt.y += ShapePoints[j].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = ShapePoints[j].z;
Vert->v = 0;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na początku odcinka
Vert++;
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos2;
pt.y += ShapePoints[j].y;
Vert->nx = norm.x; // niekoniecznie tak
Vert->ny = norm.y;
Vert->nz = norm.z;
Vert->u = ShapePoints[j].z;
Vert->v = fLength / fTextureLength;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na końcu odcinka
Vert++;
}
}
};
void TSegment::RaAnimate(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
double fTextureLength, int iSkip, int iEnd, double fOffsetX)
{ // jak wyżej, tylko z pominięciem mapowania i braku trapezowania
vector3 pos1, pos2, dir, parallel1, parallel2, pt;
double s, step, fOffset, t, fEnd;
int i, j;
bool trapez = iNumShapePoints < 0; // sygnalizacja trapezowatości
iNumShapePoints = abs(iNumShapePoints);
if (bCurve)
{
double m1, jmm1, m2, jmm2; // pozycje względne na odcinku 0...1 (ale nie parametr Beziera)
step = fStep;
s = fStep * iSkip; // iSkip - ile odcinków z początku pominąć
i = iSkip; // domyślnie 0
t = fTsBuffer[i]; // tabela wattości t dla segmentów
fOffset = 0.1 / fLength; // pierwsze 10cm
pos1 = FastGetPoint(t); // wektor początku segmentu
dir = FastGetDirection(t, fOffset); // wektor kierunku
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0))); //wektor prostopadły
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
if (iEnd == 0)
iEnd = iSegCount;
fEnd = fLength * double(iEnd) / double(iSegCount);
m2 = s / fEnd;
jmm2 = 1.0 - m2;
while (i < iEnd)
{
++i; // kolejny punkt łamanej
s += step; // końcowa pozycja segmentu [m]
m1 = m2;
jmm1 = jmm2; // stara pozycja
m2 = s / fEnd;
jmm2 = 1.0 - m2; // nowa pozycja
if (i == iEnd)
{ // gdy przekroczyliśmy koniec - stąd dziury w torach...
step -= (s - fEnd); // jeszcze do wyliczenia mapowania potrzebny
s = fEnd;
// i=iEnd; //20/5 ma dawać 4
m2 = 1.0;
jmm2 = 0.0;
}
t = fTsBuffer[i]; // szybsze od GetTFromS(s);
pos2 = FastGetPoint(t);
dir = FastGetDirection(t, fOffset); // nowy wektor kierunku
// parallel2=Normalize(CrossProduct(dir,vector3(0,1,0)));
parallel2 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
if (trapez)
for (j = 0; j < iNumShapePoints; j++)
{ // współrzędne początku
pt = parallel1 * (jmm1 * (ShapePoints[j].x - fOffsetX) +
m1 * ShapePoints[j + iNumShapePoints].x) +
pos1;
pt.y += jmm1 * ShapePoints[j].y + m1 * ShapePoints[j + iNumShapePoints].y;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na początku odcinka
Vert++;
// dla trapezu drugi koniec ma inne współrzędne
pt = parallel2 * (jmm2 * (ShapePoints[j].x - fOffsetX) +
m2 * ShapePoints[j + iNumShapePoints].x) +
pos2;
pt.y += jmm2 * ShapePoints[j].y + m2 * ShapePoints[j + iNumShapePoints].y;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na końcu odcinka
Vert++;
}
pos1 = pos2;
parallel1 = parallel2;
}
}
else
{ // gdy prosty
pos1 = FastGetPoint((fStep * iSkip) / fLength);
pos2 = FastGetPoint_1();
dir = GetDirection();
// parallel1=Normalize(CrossProduct(dir,vector3(0,1,0)));
parallel1 = Normalize(vector3(-dir.z, 0.0, dir.x)); // wektor poprzeczny
if (trapez)
for (j = 0; j < iNumShapePoints; j++)
{
pt = parallel1 * (ShapePoints[j].x - fOffsetX) + pos1;
pt.y += ShapePoints[j].y;
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na początku odcinka
Vert++;
pt = parallel1 * (ShapePoints[j + iNumShapePoints].x - fOffsetX) +
pos2; // odsunięcie
pt.y += ShapePoints[j + iNumShapePoints].y; // wysokość
Vert->x = pt.x;
Vert->y = pt.y;
Vert->z = pt.z; // punkt na końcu odcinka
Vert++;
}
}
};
//---------------------------------------------------------------------------

View File

@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
#include "VBO.h"
#include "dumb3d.h"
#include "Classes.h"
#include "usefull.h"
using namespace Math3D;
@@ -61,8 +62,6 @@ class TSegment
double fDirection = 0.0; // Ra: kąt prostego w planie; dla łuku kąt od Point1
double fStoop = 0.0; // Ra: kąt wzniesienia; dla łuku od Point1
vector3 vA, vB, vC; // współczynniki wielomianów trzeciego stopnia vD==Point1
// TSegment *pPrev; //odcinek od strony punktu 1 - w segmencie, żeby nie skakać na zwrotnicach
// TSegment *pNext; //odcinek od strony punktu 2
TTrack *pOwner = nullptr; // wskaźnik na właściciela
double fAngle[2]; // kąty zakończenia drogi na przejazdach
@@ -71,12 +70,8 @@ class TSegment
double GetTFromS(double s);
vector3 RaInterpolate(double t);
vector3 RaInterpolate0(double t);
// TSegment *segNeightbour[2]; //sąsiednie odcinki - musi być przeniesione z Track
// int iNeightbour[2]; //do którego końca doczepiony
public:
bool bCurve = false;
// int iShape; //Ra: flagi kształtu dadzą więcej możliwości optymalizacji
// (0-Bezier,1-prosty,2/3-łuk w lewo/prawo,6/7-przejściowa w lewo/prawo)
TSegment(TTrack *owner);
~TSegment();
bool Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1 = 0,
@@ -109,21 +104,16 @@ class TSegment
{
return Point2;
};
inline double GetRoll(double s)
inline double GetRoll(double const Distance)
{
s /= fLength;
return ((1.0 - s) * fRoll1 + s * fRoll2);
return interpolate( fRoll1, fRoll2, Distance / fLength );
}
void GetRolls(double &r1, double &r2)
{ // pobranie przechyłek (do generowania trójkątów)
r1 = fRoll1;
r2 = fRoll2;
}
void RenderLoft(const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength,
int iSkip = 0, int iQualityFactor = 1, vector3 **p = NULL, bool bRender = true);
void RenderSwitchRail(const vector6 *ShapePoints1, const vector6 *ShapePoints2,
int iNumShapePoints, double fTextureLength, int iSkip = 0,
double fOffsetX = 0.0f);
void RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, bool Onlypositions = false, vector3 **p = nullptr, bool bRender = true);
void Render();
inline double GetLength()
{
@@ -143,15 +133,10 @@ class TSegment
{
return fTsBuffer ? iSegCount : 1;
};
void RaRenderLoft(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
double fTextureLength, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0);
void RaAnimate(CVertNormTex *&Vert, const vector6 *ShapePoints, int iNumShapePoints,
double fTextureLength, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0);
void AngleSet(int i, double a)
{
fAngle[i] = a;
};
void Rollment(double w1, double w2); // poprawianie przechyłki
};
//---------------------------------------------------------------------------

1298
Track.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -104,14 +104,8 @@ class vector3
return &x;
}
// union
// {
// struct
// {
double x, y, z;
// };
// scalar_t e[3];
// };
bool inline Equal(vector3 *v)
{ // sprawdzenie odległości punktów
if (std::fabs(x - v->x) > 0.02)

View File

@@ -11,8 +11,11 @@ http://mozilla.org/MPL/2.0/.
#include "renderer.h"
#include "globals.h"
#include "timer.h"
#include "world.h"
#include "dynobj.h"
#include "animmodel.h"
#include "traction.h"
#include "uilayer.h"
#include "logs.h"
#include "usefull.h"
@@ -31,11 +34,11 @@ bool
opengl_camera::visible( TDynamicObject const *Dynamic ) const {
// sphere test is faster than AABB, so we'll use it here
float3 diagonal(
Dynamic->MoverParameters->Dim.L,
Dynamic->MoverParameters->Dim.H,
Dynamic->MoverParameters->Dim.W );
float const radius = diagonal.Length() * 0.5f;
glm::vec3 diagonal(
static_cast<float>( Dynamic->MoverParameters->Dim.L ),
static_cast<float>( Dynamic->MoverParameters->Dim.H ),
static_cast<float>( Dynamic->MoverParameters->Dim.W ) );
float const radius = glm::length( diagonal ) * 0.5f;
return ( m_frustum.sphere_inside( Dynamic->GetPosition(), radius ) > 0.0f );
}
@@ -183,7 +186,7 @@ opengl_renderer::Render( world_environment *Environment ) {
if( Global::fFogEnd > 0 ) {
// fog setup
::glFogfv( GL_FOG_COLOR, Global::FogColor );
::glFogf( GL_FOG_DENSITY, 1.0f / Global::fFogEnd );
::glFogf( GL_FOG_DENSITY, static_cast<GLfloat>( 1.0 / Global::fFogEnd ) );
::glEnable( GL_FOG );
}
else { ::glDisable( GL_FOG ); }
@@ -236,7 +239,7 @@ opengl_renderer::Render( world_environment *Environment ) {
{
Bind( m_moontextureid );
float3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, 1.0f - Global::fLuminance * 0.5f );
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 1.0 - Global::fLuminance * 0.5 ) );
auto const moonvector = Environment->m_moon.getDirection();
auto const moonposition = modelview * glm::vec4( moonvector.x, moonvector.y, moonvector.z, 1.0f );
@@ -296,9 +299,9 @@ opengl_renderer::Render( TGround *Ground ) {
glEnable( GL_LIGHTING );
glColor3f( 1.0f, 1.0f, 1.0f );
float3 const cameraposition = float3( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
int const camerax = std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2;
int const cameraz = std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2;
glm::vec3 const cameraposition( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 );
int const cameraz = static_cast<int>( std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2 );
int const segmentcount = 2 * static_cast<int>(std::ceil( m_drawrange * Global::fDistanceFactor / 1000.0f ));
int const originx = std::max( 0, camerax - segmentcount / 2 );
int const originz = std::max( 0, cameraz - segmentcount / 2 );
@@ -317,15 +320,133 @@ opengl_renderer::Render( TGround *Ground ) {
}
bool
opengl_renderer::Render( TDynamicObject *Dynamic ) {
opengl_renderer::Render( TGroundNode *Node ) {
if( false == m_camera.visible( Dynamic ) ) {
Node->SetLastUsage( Timer::GetSimulationTime() );
Dynamic->renderme = false;
switch (Node->iType)
{ // obiekty renderowane niezależnie od odległości
case TP_SUBMODEL:
TSubModel::fSquareDist = 0;
Render( Node->smTerrain );
return true;
}
double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
return false;
}
Dynamic->renderme = true;
switch (Node->iType)
{
case TP_TRACK: {
// TODO: unify the render code after generic buffers are in place
if( Global::bUseVBO ) {
if( Node->iNumVerts ) {
Node->pTrack->RaRenderVBO( Node->iVboPtr );
}
else {
return false;
}
}
else {
Node->pTrack->Render();
}
return true;
}
case TP_MODEL: {
Node->Model->Render( &Node->pCenter );
return true;
}
case TP_MEMCELL: {
GfxRenderer.Render( Node->MemCell );
return true;
}
}
// TODO: sprawdzic czy jest potrzebny warunek fLineThickness < 0
if( ( Node->iFlags & 0x10 )
|| ( Node->fLineThickness < 0 ) ) {
// TODO: unify the render code after generic buffers are in place
if( false == Global::bUseVBO ) {
// additional setup for display lists
if( ( Node->DisplayListID == 0 )
|| ( Node->iVersion != Global::iReCompile ) ) { // Ra: wymuszenie rekompilacji
Node->Compile();
if( Global::bManageNodes )
ResourceManager::Register( Node );
};
}
if( ( Node->iType == GL_LINES )
|| ( Node->iType == GL_LINE_STRIP )
|| ( Node->iType == GL_LINE_LOOP ) ) {
// wszelkie linie są rysowane na samym końcu
if( Node->iNumPts ) {
// setup
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] ) ),
static_cast<GLubyte>( std::min( 255.0, 255000 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) );
GfxRenderer.Bind( 0 );
// render
// TODO: unify the render code after generic buffers are in place
if( Global::bUseVBO ) {
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
}
else {
::glCallList( Node->DisplayListID );
}
return true;
}
else {
return false;
}
}
else {
// GL_TRIANGLE etc
// setup
::glColor3ub(
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
static_cast<GLubyte>( Node->Diffuse[ 2 ] ) );
Bind( Node->TextureID );
// render
// TODO: unify the render code after generic buffers are in place
if( Global::bUseVBO ) {
// vbo render path
if( Node->iVboPtr >= 0 ) {
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
}
else {
return false;
}
}
else {
// display list render path
::glCallList( Node->DisplayListID );
}
return true;
}
}
// in theory we shouldn't ever get here but, eh
return false;
}
bool
opengl_renderer::Render( TDynamicObject *Dynamic ) {
Dynamic->renderme = m_camera.visible( Dynamic );
if( false == Dynamic->renderme ) {
return false;
}
// setup
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
@@ -517,7 +638,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
float const anglefactor = ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
// distance attenuation. NOTE: since it's fixed pipeline with built-in gamma correction we're using linear attenuation
// we're capping how much effect the distance attenuation can have, otherwise the lights get too tiny at regular distances
float const distancefactor = std::max( 0.5, ( Submodel->fSquareMaxDist - TSubModel::fSquareDist ) / ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) );
float const distancefactor = static_cast<float>( std::max( 0.5, ( Submodel->fSquareMaxDist - TSubModel::fSquareDist ) / ( Submodel->fSquareMaxDist * Global::fDistanceFactor ) ) );
if( lightlevel > 0.0f ) {
// material configuration:
@@ -609,6 +730,146 @@ opengl_renderer::Render( TMemCell *Memcell ) {
::glPopAttrib();
}
// NOTE: legacy render system switch
#define _PROBLEND
bool
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// SPOSOB NA POZBYCIE SIE RAMKI DOOKOLA TEXTURY ALPHA DLA OBIEKTOW ZAGNIEZDZONYCH W SCN JAKO
// NODE
// W GROUND.H dajemy do klasy TGroundNode zmienna bool PROBLEND to samo robimy w klasie TGround
// nastepnie podczas wczytywania textury dla TRIANGLES w TGround::AddGroundNode
// sprawdzamy czy w nazwie jest @ i wg tego
// ustawiamy PROBLEND na true dla wlasnie wczytywanego trojkata (kazdy trojkat jest osobnym
// nodem)
// nastepnie podczas renderowania w bool TGroundNode::RenderAlpha()
// na poczatku ustawiamy standardowe GL_GREATER = 0.04
// pozniej sprawdzamy czy jest wlaczony PROBLEND dla aktualnie renderowanego noda TRIANGLE,
// wlasciwie dla kazdego node'a
// i jezeli tak to odpowiedni GL_GREATER w przeciwnym wypadku standardowy 0.04
Node->SetLastUsage( Timer::GetSimulationTime() );
double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
return false;
}
switch (Node->iType)
{
case TP_TRACTION: {
// TODO: unify the render code after generic buffers are in place
if( Node->bVisible ) {
if( Global::bUseVBO ) {
Node->hvTraction->RenderVBO( distancesquared, Node->iVboPtr );
}
else {
Node->hvTraction->RenderDL( distancesquared );
}
return true;
}
else {
return false;
}
}
case TP_MODEL: {
Node->Model->RenderAlpha( &Node->pCenter );
return true;
}
}
// TODO: sprawdzic czy jest potrzebny warunek fLineThickness < 0
if( ( Node->iNumVerts && ( Node->iFlags & 0x20 ) )
|| ( Node->iNumPts && ( Node->fLineThickness > 0 ) ) ) {
#ifdef _PROBLEND
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
{
::glDisable( GL_BLEND );
::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
};
#endif
// TODO: unify the render code after generic buffers are in place
if( false == Global::bUseVBO ) {
// additional setup for display lists
if( ( Node->DisplayListID == 0 )
|| ( Node->iVersion != Global::iReCompile ) ) { // Ra: wymuszenie rekompilacji
Node->Compile();
if( Global::bManageNodes )
ResourceManager::Register( Node );
};
}
bool result( false );
if( ( Node->iType == GL_LINES )
|| ( Node->iType == GL_LINE_STRIP )
|| ( Node->iType == GL_LINE_LOOP ) ) {
// wszelkie linie są rysowane na samym końcu
if( Node->iNumPts ) {
// setup
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 1 ] * Global::DayLight.ambient[ 1 ] ) ),
static_cast<GLubyte>( std::floor( Node->Diffuse[ 2 ] * Global::DayLight.ambient[ 2 ] ) ),
static_cast<GLubyte>( std::min( 255.0, 255000 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) );
GfxRenderer.Bind( 0 );
// render
// TODO: unify the render code after generic buffers are in place
if( Global::bUseVBO ) {
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
}
else {
::glCallList( Node->DisplayListID );
}
result = true;
}
}
else {
// GL_TRIANGLE etc
// setup
::glColor3ub(
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
static_cast<GLubyte>( Node->Diffuse[ 2 ] ) );
Bind( Node->TextureID );
// render
// TODO: unify the render code after generic buffers are in place
if( Global::bUseVBO ) {
// vbo render path
if( Node->iVboPtr >= 0 ) {
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
result = true;
}
}
else {
// display list render path
::glCallList( Node->DisplayListID );
result = true;
}
}
// post-render cleanup
#ifdef _PROBLEND
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
{
::glEnable( GL_BLEND );
::glAlphaFunc( GL_GREATER, 0.04f );
}
#endif
return result;
}
// in theory we shouldn't ever get here but, eh
return false;
}
bool
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
@@ -978,12 +1239,12 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
if( environment > 0.0f ) {
luminance *= environment;
}
renderlight->diffuse[ 0 ] = std::max( 0.0, scenelight.color.x - luminance );
renderlight->diffuse[ 1 ] = std::max( 0.0, scenelight.color.y - luminance );
renderlight->diffuse[ 2 ] = std::max( 0.0, scenelight.color.z - luminance );
renderlight->ambient[ 0 ] = std::max( 0.0, scenelight.color.x * scenelight.intensity - luminance);
renderlight->ambient[ 1 ] = std::max( 0.0, scenelight.color.y * scenelight.intensity - luminance );
renderlight->ambient[ 2 ] = std::max( 0.0, scenelight.color.z * scenelight.intensity - luminance );
renderlight->diffuse[ 0 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.x - luminance ) );
renderlight->diffuse[ 1 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.y - luminance ) );
renderlight->diffuse[ 2 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.z - luminance ) );
renderlight->ambient[ 0 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.x * scenelight.intensity - luminance) );
renderlight->ambient[ 1 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.y * scenelight.intensity - luminance ) );
renderlight->ambient[ 2 ] = static_cast<GLfloat>( std::max( 0.0, scenelight.color.z * scenelight.intensity - luminance ) );
/*
// NOTE: we have no simple way to determine whether the lights are falling on objects located in darker environment
// until this issue is resolved we're disabling reduction of light strenght based on the global luminance
@@ -994,7 +1255,7 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
renderlight->ambient[ 1 ] = std::max( 0.0f, scenelight.color.y * scenelight.intensity );
renderlight->ambient[ 2 ] = std::max( 0.0f, scenelight.color.z * scenelight.intensity );
*/
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, (0.25f * scenelight.count) / std::pow( scenelight.count, 2 ) * (scenelight.owner->DimHeadlights ? 1.25f : 1.0f) );
::glLightf( renderlight->id, GL_LINEAR_ATTENUATION, static_cast<GLfloat>( (0.25 * scenelight.count) / std::pow( scenelight.count, 2 ) * (scenelight.owner->DimHeadlights ? 1.25 : 1.0) ) );
::glEnable( renderlight->id );
renderlight->apply_intensity();

View File

@@ -124,6 +124,8 @@ public:
Render( world_environment *Environment );
bool
Render( TGround *Ground );
bool
Render( TGroundNode *Node );
bool
Render( TDynamicObject *Dynamic );
bool
@@ -134,6 +136,8 @@ public:
Render( TSubModel *Submodel );
void
Render( TMemCell *Memcell );
bool
Render_Alpha( TGroundNode *Node );
bool
Render_Alpha( TDynamicObject *Dynamic );
bool