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

camera-centric rendering, initial implementation

This commit is contained in:
tmj-fstate
2017-05-25 12:58:43 +02:00
parent ac61dbdf14
commit 2b6ea903bc
15 changed files with 385 additions and 357 deletions

View File

@@ -606,16 +606,16 @@ int TAnimModel::Flags()
//-----------------------------------------------------------------------------
// 2011-03-16 funkcje renderowania z możliwością pochylania obiektów
//-----------------------------------------------------------------------------
void TAnimModel::Render( vector3 *vPosition ) {
void TAnimModel::Render( vector3 const &Position ) {
RaAnimate(); // jednorazowe przeliczenie animacji
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
GfxRenderer.Render( pModel, Material(), *vPosition, vAngle );
GfxRenderer.Render( pModel, Material(), Position, vAngle );
};
void TAnimModel::RenderAlpha( vector3 *vPosition ) {
void TAnimModel::RenderAlpha( vector3 const &Position ) {
RaPrepare();
if( pModel ) // renderowanie rekurencyjne submodeli
GfxRenderer.Render_Alpha( pModel, Material(), *vPosition, vAngle );
GfxRenderer.Render_Alpha( pModel, Material(), Position, vAngle );
};
//---------------------------------------------------------------------------

View File

@@ -161,8 +161,8 @@ class TAnimModel
bool Load(cParser *parser, bool ter = false);
TAnimContainer * AddContainer(char *pName);
TAnimContainer * GetContainer(char *pName);
void Render( vector3 *vPosition );
void RenderAlpha( vector3 *vPosition );
void Render( vector3 const &Position );
void RenderAlpha( vector3 const &Position );
int Flags();
void RaAnglesSet(double a, double b, double c)
{

View File

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

View File

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

View File

@@ -248,43 +248,6 @@ void TGroundNode::InitNormals()
}
}
void TGroundNode::MoveMe(vector3 pPosition)
{ // przesuwanie obiektów scenerii o wektor w celu redukcji trzęsienia
pCenter += pPosition;
switch (iType)
{
case TP_TRACTION:
hvTraction->pPoint1 += pPosition;
hvTraction->pPoint2 += pPosition;
hvTraction->pPoint3 += pPosition;
hvTraction->pPoint4 += pPosition;
hvTraction->Optimize();
break;
case TP_MODEL:
case TP_DYNAMIC:
case TP_MEMCELL:
case TP_EVLAUNCH:
break;
case TP_TRACK:
pTrack->MoveMe(pPosition);
break;
case TP_SOUND: // McZapkie - dzwiek zapetlony w zaleznosci od odleglosci
tsStaticSound->vSoundPosition += pPosition;
break;
case GL_LINES:
case GL_LINE_STRIP:
case GL_LINE_LOOP:
for (int i = 0; i < iNumPts; i++)
Points[i] += pPosition;
ResourceManager::Unregister(this);
break;
default:
for (int i = 0; i < iNumVerts; i++)
Vertices[i].Point += pPosition;
ResourceManager::Unregister(this);
}
}
void TGroundNode::RaRenderVBO()
{ // renderowanie z domyslnego bufora VBO
glColor3ub(Diffuse[0], Diffuse[1], Diffuse[2]);
@@ -309,7 +272,10 @@ void TGroundNode::Compile(bool many)
{
glBegin(iType);
for (int i = 0; i < iNumPts; ++i)
glVertex3dv(&Points[i].x);
glVertex3d(
Points[i].x - m_rootposition.x,
Points[i].y - m_rootposition.y,
Points[i].z - m_rootposition.z );
glEnd();
}
else if (iType == GL_TRIANGLE_STRIP || iType == GL_TRIANGLE_FAN || iType == GL_TRIANGLES)
@@ -323,9 +289,14 @@ void TGroundNode::Compile(bool many)
for (int i = 0; i < iNumVerts; ++i)
{
glNormal3dv(&Vertices[i].Normal.x);
glTexCoord2f(Vertices[i].tu, Vertices[i].tv);
glVertex3dv(&Vertices[i].Point.x);
};
glTexCoord2f(
Vertices[i].tu,
Vertices[i].tv);
glVertex3d(
Points[i].x - m_rootposition.x,
Points[i].y - m_rootposition.y,
Points[i].z - m_rootposition.z );
}
glEnd();
}
else if (iType == TP_MESH)
@@ -408,6 +379,9 @@ void TSubRect::NodeAdd(TGroundNode *Node)
// nRenderAlpha - lista grup renderowanych z własnych VBO albo DL z przezroczystością
// nRenderWires - lista grup renderowanych z własnych VBO albo DL - druty i linie
// nMeshed - obiekty do pogrupowania wg tekstur
Node->m_rootposition = Math3D::vector3( m_area.center.x, m_area.center.y, m_area.center.z ) ;
switch (Node->iType)
{
case TP_SOUND: // te obiekty są sprawdzanie niezależnie od kierunku patrzenia
@@ -418,11 +392,11 @@ void TSubRect::NodeAdd(TGroundNode *Node)
case TP_TRACK: // TODO: tory z cieniem (tunel, canyon) też dać bez łączenia?
++iTracks; // jeden tor więcej
Node->pTrack->RaOwnerSet(this); // do którego sektora ma zgłaszać animację
// if (Global::bUseVBO?false:!Node->pTrack->IsGroupable())
if (Global::bUseVBO ? true :
!Node->pTrack->IsGroupable()) // TODO: tymczasowo dla VBO wyłączone
RaNodeAdd(
Node); // tory ruchome nie są grupowane przy Display Lists (wymagają odświeżania DL)
if( ( true == Global::bUseVBO )
|| ( false == Node->pTrack->IsGroupable() ) ) {
// tory ruchome nie są grupowane przy Display Lists (wymagają odświeżania DL)
RaNodeAdd( Node );
}
else
{ // tory nieruchome mogą być pogrupowane wg tekstury, przy VBO wszystkie
Node->TextureID = Node->pTrack->TextureGet(0); // pobranie tekstury do sortowania
@@ -800,9 +774,9 @@ void TSubRect::LoadNodes()
case GL_TRIANGLES:
for (i = 0; i < n->iNumVerts; ++i)
{ // Ra: trójkąty można od razu wczytywać do takich tablic... to może poczekać
m_pVNT[n->iVboPtr + i].x = n->Vertices[i].Point.x;
m_pVNT[n->iVboPtr + i].y = n->Vertices[i].Point.y;
m_pVNT[n->iVboPtr + i].z = n->Vertices[i].Point.z;
m_pVNT[n->iVboPtr + i].x = n->Vertices[i].Point.x - n->m_rootposition.x;
m_pVNT[n->iVboPtr + i].y = n->Vertices[i].Point.y - n->m_rootposition.y;
m_pVNT[n->iVboPtr + i].z = n->Vertices[i].Point.z - n->m_rootposition.z;
m_pVNT[n->iVboPtr + i].nx = n->Vertices[i].Normal.x;
m_pVNT[n->iVboPtr + i].ny = n->Vertices[i].Normal.y;
m_pVNT[n->iVboPtr + i].nz = n->Vertices[i].Normal.z;
@@ -815,9 +789,9 @@ void TSubRect::LoadNodes()
case GL_LINE_LOOP:
for (i = 0; i < n->iNumPts; ++i)
{
m_pVNT[n->iVboPtr + i].x = n->Points[i].x;
m_pVNT[n->iVboPtr + i].y = n->Points[i].y;
m_pVNT[n->iVboPtr + i].z = n->Points[i].z;
m_pVNT[n->iVboPtr + i].x = n->Points[i].x - n->m_rootposition.x;
m_pVNT[n->iVboPtr + i].y = n->Points[i].y - n->m_rootposition.y;
m_pVNT[n->iVboPtr + i].z = n->Points[i].z - n->m_rootposition.z;
// miejsce w tablicach normalnych i teksturowania się marnuje...
}
break;
@@ -833,7 +807,7 @@ void TSubRect::LoadNodes()
case TP_TRACTION:
if( n->iNumVerts ) { // druty mogą być niewidoczne...?
#ifdef EU07_USE_OLD_VERTEXBUFFER
n->hvTraction->RaArrayFill( m_pVNT + n->iVboPtr );
n->hvTraction->RaArrayFill( m_pVNT + n->iVboPtr, n->m_rootposition );
#else
n->hvTraction->RaArrayFill( m_pVNT.data() + n->iVboPtr );
#endif
@@ -960,12 +934,14 @@ TGroundRect::Init() {
float const subrectsize = 1000.0f / iNumSubRects;
for( int column = 0; column < iNumSubRects; ++column ) {
for( int row = 0; row < iNumSubRects; ++row ) {
auto &area = FastGetRect(column, row)->m_area;
auto &area = SafeGetRect(column, row)->m_area;
area.center =
m_area.center
- float3( 500.0f, 0.0f, 500.0f ) // 'upper left' corner of rectangle
+ float3( subrectsize * 0.5f, 0.0f, subrectsize * 0.5f ) // center of sub-rectangle
+ float3( subrectsize * column, 0.0f, subrectsize * row );
- glm::vec3( 500.0f, 0.0f, 500.0f ) // 'upper left' corner of rectangle
+ glm::vec3( subrectsize * 0.5f, 0.0f, subrectsize * 0.5f ) // center of sub-rectangle
+ glm::vec3( subrectsize * column, 0.0f, subrectsize * row );
// NOTE: the actual coordinates get swapped, as they're swapped in rest of the code :x
area.center = glm::vec3( area.center.z, area.center.y, area.center.x );
area.radius = subrectsize * M_SQRT2;
}
}
@@ -1051,17 +1027,17 @@ TGround::TGround()
// set bounding area information for ground rectangles
float const rectsize = 1000.0f;
float3 const worldcenter( 0.0f, 0.0f, 0.0f );
glm::vec3 const worldcenter( 0.0f, 0.0f, 0.0f );
for( int column = 0; column < iNumRects; ++column ) {
for( int row = 0; row < iNumRects; ++row ) {
auto &area = Rects[ column ][ row ].m_area;
// NOTE: in current implementation triangles can stick out to ~200m from the area, so we add extra padding
area.radius = 200.0f + rectsize * 0.5f * M_SQRT2;
area.radius = ( rectsize * 0.5f * M_SQRT2 ) + 200.0f;
area.center =
worldcenter
- float3( (iNumRects / 2) * rectsize, 0.0f, (iNumRects / 2) * rectsize ) // 'upper left' corner of the world
+ float3( rectsize * 0.5f, 0.0f, rectsize * 0.5f ) // center of the rectangle
+ float3( rectsize * column, 0.0f, rectsize * row );
- glm::vec3( (iNumRects / 2) * rectsize, 0.0f, (iNumRects / 2) * rectsize ) // 'upper left' corner of the world
+ glm::vec3( rectsize * 0.5f, 0.0f, rectsize * 0.5f ) // center of the rectangle
+ glm::vec3( rectsize * column, 0.0f, rectsize * row );
}
}
}
@@ -1995,39 +1971,38 @@ void TGround::FirstInit()
gr->RaNodeAdd(&Current->nNode[j]);
}
}
// else if
// ((Current->iType!=GL_TRIANGLES)&&(Current->iType!=GL_TRIANGLE_STRIP)?true
// //~czy trójkąt?
else if ((Current->iType != GL_TRIANGLES) ?
true //~czy trójkąt?
:
(Current->iFlags & 0x20) ?
true //~czy teksturę ma nieprzezroczystą?
:
(Current->fSquareMinRadius != 0.0) ?
true //~czy widoczny z bliska?
:
(Current->fSquareRadius <= 90000.0)) //~czy widoczny z daleka?
GetSubRect(Current->pCenter.x, Current->pCenter.z)->NodeAdd(Current);
else // dodajemy do kwadratu kilometrowego
GetRect(Current->pCenter.x, Current->pCenter.z)->NodeAdd(Current);
else if( ( Current->iType != GL_TRIANGLES )
|| ( Current->iFlags & 0x20 )
|| ( Current->fSquareMinRadius != 0.0 )
|| ( Current->fSquareRadius <= 90000.0 ) ) {
// add to sub-rectangle
GetSubRect( Current->pCenter.x, Current->pCenter.z )->NodeAdd( Current );
}
else {
// dodajemy do kwadratu kilometrowego
GetRect( Current->pCenter.x, Current->pCenter.z )->NodeAdd( Current );
}
}
// if (Current->iType!=TP_DYNAMIC)
// GetSubRect(Current->pCenter.x,Current->pCenter.z)->AddNode(Current);
}
}
for (i = 0; i < iNumRects; ++i)
for (j = 0; j < iNumRects; ++j)
Rects[i][j].Optimize(); // optymalizacja obiektów w sektorach
WriteLog("InitNormals OK");
InitTracks(); //łączenie odcinków ze sobą i przyklejanie eventów
WriteLog("InitTracks OK");
InitTraction(); //łączenie drutów ze sobą
WriteLog("InitTraction OK");
InitEvents();
WriteLog("InitEvents OK");
InitLaunchers();
WriteLog("InitLaunchers OK");
WriteLog("FirstInit is done");
};
@@ -2077,13 +2052,14 @@ bool TGround::Init(std::string File)
}
else if ( ( LastNode->iType == TP_TRACTION ) && ( false == Global::bLoadTraction ) )
SafeDelete(LastNode); // usuwamy druty, jeśli wyłączone
if (LastNode) // dopiero na koniec dopisujemy do tablic
if (LastNode->iType != TP_DYNAMIC)
{ // jeśli nie jest pojazdem
LastNode->nNext = nRootOfType[LastNode->iType]; // ostatni dodany dołączamy
// na końcu nowego
nRootOfType[LastNode->iType] =
LastNode; // ustawienie nowego na początku listy
// ostatni dodany dołączamy na końcu nowego
LastNode->nNext = nRootOfType[LastNode->iType];
// ustawienie nowego na początku listy
nRootOfType[LastNode->iType] = LastNode;
iNumNodes++;
}
else
@@ -2437,10 +2413,6 @@ bool TGround::Init(std::string File)
else // jak liczba to na pewno błąd
Error("Unrecognized command: " + str);
}
/* else if (str == "")
break;
*/
// LastNode=NULL;
token = "";
parser.getTokens();

View File

@@ -122,19 +122,20 @@ public:
TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
};
std::string asName; // nazwa (nie zawsze ma znaczenie)
vector3 pCenter; // współrzędne środka do przydzielenia sektora
vector3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
// visualization-related data
// TODO: wrap these in a struct, when cleaning objects up
union
{
int iNumVerts; // dla trójkątów
int iNumPts; // dla linii
int iCount; // dla terenu
// int iState; //Ra: nie używane - dźwięki zapętlone
};
vector3 pCenter; // współrzędne środka do przydzielenia sektora
double fLineThickness; // McZapkie-120702: grubosc linii
double fSquareRadius; // kwadrat widoczności do
double fSquareMinRadius; // kwadrat widoczności od
// TGroundNode *nMeshGroup; //Ra: obiekt grupujący trójkąty w TSubRect dla tekstury
int iVersion; // wersja siatki (do wykonania rekompilacji)
// union ?
GLuint DisplayListID; // numer siatki DisplayLists
@@ -144,6 +145,7 @@ public:
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
int Ambient[4], Diffuse[4], Specular[4]; // oświetlenie
bool bVisible;
TGroundNode *nNext; // lista wszystkich w scenerii, ostatni na początku
TGroundNode *nNext2; // lista obiektów w sektorze
TGroundNode *nNext3; // lista obiektów renderowanych we wspólnym cyklu
@@ -154,8 +156,6 @@ public:
void InitCenter(); // obliczenie współrzędnych środka
void InitNormals();
void MoveMe(vector3 pPosition); // przesuwanie (nie działa)
// bool Disable();
inline TGroundNode * Find(const std::string &asNameToFind, TGroundNodeType iNodeType)
{ // wyszukiwanie czołgowe z typem
@@ -177,7 +177,7 @@ public:
struct bounding_area {
float3 center; // mid point of the rectangle
glm::vec3 center; // mid point of the rectangle
float radius{ 0.0f }; // radius of the bounding sphere
};

View File

@@ -319,7 +319,7 @@ vector3 TSegment::FastGetPoint(double t)
return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2));
}
int 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)
int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, vector3 **p, bool bRender)
{ // generowanie trójkątów dla odcinka trajektorii ruchu
// standardowo tworzy triangle_strip dla prostego albo ich zestaw dla łuku
// po modyfikacji - dla ujemnego (iNumShapePoints) w dodatkowych polach tabeli
@@ -368,12 +368,10 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int
jmm2 = 0.0;
}
if( false == Onlypositions ) {
while( tv1 < 0.0 ) {
tv1 += 1.0;
}
tv2 = tv1 - step / fTextureLength; // mapowanie na końcu segmentu
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 );
@@ -389,30 +387,25 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int
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;
}
pt -= Origin;
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel1;
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
if( Output == nullptr ) {
// immediate mode
if( false == Onlypositions ) {
::glNormal3f( norm.x, norm.y, norm.z );
::glTexCoord2f( (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv1 );
}
::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->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->v = tv1;
++Output;
}
++vertexcount;
@@ -427,30 +420,25 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int
// 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;
}
pt -= Origin;
norm = ( jmm1 * ShapePoints[ j ].n.x + m1 * ShapePoints[ j + iNumShapePoints ].n.x ) * parallel2;
norm.y += jmm1 * ShapePoints[ j ].n.y + m1 * ShapePoints[ j + iNumShapePoints ].n.y;
if( bRender ) { // skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
if( Output == nullptr ) {
// immediate mode
if( false == Onlypositions ) {
::glNormal3f( norm.x, norm.y, norm.z );
::glTexCoord2f( (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale, tv2 );
}
::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->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
Output->v = tv2;
++Output;
}
++vertexcount;
@@ -470,58 +458,48 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int
//ł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;
}
pt -= Origin;
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 );
}
::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->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv1;
++Output;
}
++vertexcount;
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;
}
pt -= Origin;
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 );
}
::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->nx = norm.x;
Output->ny = norm.y;
Output->nz = norm.z;
Output->u = ShapePoints[ j ].z / Texturescale;
Output->v = tv2;
++Output;
}
++vertexcount;
@@ -534,9 +512,7 @@ int TSegment::RenderLoft( CVertNormTex* &Output, const vector6 *ShapePoints, int
}
pos1 = pos2;
parallel1 = parallel2;
if( false == Onlypositions ) {
tv1 = tv2;
}
tv1 = tv2;
}
return vertexcount;

View File

@@ -113,7 +113,7 @@ class TSegment
r1 = fRoll1;
r2 = fRoll2;
}
int 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);
int RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, vector3 **p = nullptr, bool bRender = true);
void Render();
inline double GetLength()
{

153
Track.cpp
View File

@@ -1090,6 +1090,9 @@ void TTrack::Compile(GLuint tex)
hypot2 = hypot1;
normal2 = normal1;
}
auto const origin = pMyNode->m_rootposition;
double roll1, roll2;
switch (iCategoryFlag & 15)
{
@@ -1216,15 +1219,15 @@ void TTrack::Compile(GLuint tex)
}
if (!tex)
GfxRenderer.Bind( TextureID2 );
Segment->RenderLoft( immediate, bpts1, iTrapezoid ? -4 : 4, fTexLength);
Segment->RenderLoft( immediate, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength);
}
if (TextureID1)
if (tex ? TextureID1 == tex : true) // jeśli pasuje do grupy (tex)
{ // szyny
if (!tex)
GfxRenderer.Bind( TextureID1 );
Segment->RenderLoft( immediate, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft( immediate, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft( immediate, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft( immediate, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
}
break;
case tt_Switch: // dla zwrotnicy dwa razy szyny
@@ -1252,31 +1255,31 @@ void TTrack::Compile(GLuint tex)
{ // zwrotnica prawa
if( TextureID1 ) {
GfxRenderer.Bind( TextureID1 );
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); // prawa iglica
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 ); // prawa iglica
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała
}
if( TextureID2 ) {
GfxRenderer.Bind( TextureID2 );
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); // lewa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 ); // lewa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
}
}
else
{ // lewa kiedyś działała lepiej niż prawa
if( TextureID1 ) {
GfxRenderer.Bind( TextureID1 );
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // lewa iglica
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength ); // prawa szyna normalna cała
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // lewa iglica
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
}
if( TextureID2 ) {
// nie wiadomo, czy OpenGL to optymalizuje
GfxRenderer.Bind( TextureID2 );
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // prawa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // prawa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts2, nnumPts, fTexLength ); // lewa szyna normalnie cała
}
}
}
@@ -1315,7 +1318,7 @@ void TTrack::Compile(GLuint tex)
{ // tworzenie trójkątów nawierzchni szosy
if (!tex)
GfxRenderer.Bind( TextureID1 );
Segment->RenderLoft( immediate, bpts1, iTrapezoid ? -2 : 2, fTexLength);
Segment->RenderLoft( immediate, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
}
if (TextureID2)
if (tex ? TextureID2 == tex : true) // jeśli pasuje do grupy (tex)
@@ -1399,16 +1402,16 @@ void TTrack::Compile(GLuint tex)
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony
// odcinka
if ((fTexHeight1 >= 0.0) ? true : (slop != 0.0))
Segment->RenderLoft( immediate, rpts1, -3, fTexLength); // tylko jeśli jest z prawej
Segment->RenderLoft( immediate, origin, rpts1, -3, fTexLength); // tylko jeśli jest z prawej
if ((fTexHeight1 >= 0.0) ? true : (side != 0.0))
Segment->RenderLoft( immediate, rpts2, -3, fTexLength); // tylko jeśli jest z lewej
Segment->RenderLoft( immediate, origin, rpts2, -3, fTexLength); // tylko jeśli jest z lewej
}
else
{ // pobocza zwykłe, brak przechyłki
if ((fTexHeight1 >= 0.0) ? true : (slop != 0.0))
Segment->RenderLoft( immediate, rpts1, 3, fTexLength);
Segment->RenderLoft( immediate, origin, rpts1, 3, fTexLength);
if ((fTexHeight1 >= 0.0) ? true : (side != 0.0))
Segment->RenderLoft( immediate, rpts2, 3, fTexLength);
Segment->RenderLoft( immediate, origin, rpts2, 3, fTexLength);
}
}
break;
@@ -1551,19 +1554,19 @@ void TTrack::Compile(GLuint tex)
if (SwitchExtension->iRoads == 4)
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 3 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 4 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 5 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
SwitchExtension->Segments[ 3 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
SwitchExtension->Segments[ 4 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
SwitchExtension->Segments[ 5 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
}
}
else
// to będzie ewentualnie dla prostego na skrzyżowaniu trzech dróg
{ // punkt 3 pokrywa się z punktem 1, jak w zwrotnicy; połączenie 1->2 nie musi być prostoliniowe
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P2 do P4
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P4 do P3=P1 (odwrócony)
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P1 do P2
SwitchExtension->Segments[ 2 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4
SwitchExtension->Segments[ 1 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony)
SwitchExtension->Segments[ 0 ]->RenderLoft( immediate, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2
}
}
}
@@ -1628,7 +1631,7 @@ void TTrack::Compile(GLuint tex)
{
if (!tex)
GfxRenderer.Bind( TextureID1 );
Segment->RenderLoft( immediate, bpts1, numPts, fTexLength);
Segment->RenderLoft( immediate, origin, bpts1, numPts, fTexLength);
}
if (TextureID2)
if (tex ? TextureID2 == tex : true) // jeśli pasuje do grupy (tex)
@@ -1640,8 +1643,8 @@ void TTrack::Compile(GLuint tex)
vector6(-rozp, -fTexHeight1, 0.0)}; // Ra: po kiego 0.1?
if (!tex)
GfxRenderer.Bind( TextureID2 ); // brzeg rzeki
Segment->RenderLoft( immediate, rpts1, 3, fTexLength);
Segment->RenderLoft( immediate, rpts2, 3, fTexLength);
Segment->RenderLoft( immediate, origin, rpts1, 3, fTexLength );
Segment->RenderLoft( immediate, origin, rpts2, 3, fTexLength );
}
break;
}
@@ -1858,6 +1861,9 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
hypot2 = hypot1;
normal2 = normal1;
}
auto const origin = pMyNode->m_rootposition;
double roll1, roll2;
switch (iCategoryFlag & 15)
{
@@ -1959,12 +1965,12 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
bpts1[3] = vector6(-rozp, -fTexHeight1 - 0.18, 0.5 + map12, -normal1.x, -normal1.y, 0.0); // prawy skos
}
}
Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -4 : 4, fTexLength);
Segment->RenderLoft(Vert, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength);
}
if (TextureID1)
{ // szyny - generujemy dwie, najwyżej rysować się będzie jedną
Segment->RenderLoft(Vert, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft(Vert, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft(Vert, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
Segment->RenderLoft(Vert, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
}
break;
case tt_Switch: // dla zwrotnicy dwa razy szyny
@@ -1989,32 +1995,32 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
if (SwitchExtension->RightSwitch)
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
if( TextureID1 ) {
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength );
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2 );
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength );
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength, 1.0, 2 );
SwitchExtension->iLeftVBO = Vert - Start; // indeks lewej iglicy
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
}
if( TextureID2 ) {
SwitchExtension->iRightVBO = Vert - Start; // indeks prawej iglicy
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength, 1.0, 2 );
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength );
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength, 1.0, 2 );
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength );
}
}
else
{ // lewa działa lepiej niż prawa
if( TextureID1 ) {
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
SwitchExtension->iLeftVBO = Vert - Start; // indeks lewej iglicy
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // prawa iglica
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // prawa iglica
}
if( TextureID2 ) {
SwitchExtension->iRightVBO = Vert - Start; // indeks prawej iglicy
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // lewa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 ); // lewa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
}
}
}
@@ -2049,7 +2055,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
}
if (TextureID1) // jeśli podana była tekstura, generujemy trójkąty
{ // tworzenie trójkątów nawierzchni szosy
Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -2 : 2, fTexLength);
Segment->RenderLoft(Vert, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
}
if (TextureID2)
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
@@ -2130,18 +2136,18 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony
// odcinka
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
Segment->RenderLoft( Vert, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej
Segment->RenderLoft( Vert, origin, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej
}
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
Segment->RenderLoft( Vert, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej
Segment->RenderLoft( Vert, origin, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej
}
}
else { // pobocza zwykłe, brak przechyłki
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
Segment->RenderLoft( Vert, rpts1, 3, fTexLength );
Segment->RenderLoft( Vert, origin, rpts1, 3, fTexLength );
}
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
Segment->RenderLoft( Vert, rpts2, 3, fTexLength );
Segment->RenderLoft( Vert, origin, rpts2, 3, fTexLength );
}
}
}
@@ -2266,18 +2272,18 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
if (SwitchExtension->iRoads == 4)
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 3 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 4 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 5 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render );
SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
SwitchExtension->Segments[ 3 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
SwitchExtension->Segments[ 4 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
SwitchExtension->Segments[ 5 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
}
}
else {
// punkt 3 pokrywa się z punktem 1, jak w zwrotnicy; połączenie 1->2 nie musi być prostoliniowe
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P2 do P4
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P4 do P3=P1 (odwrócony)
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, false, &b, render ); // z P1 do P2
SwitchExtension->Segments[ 2 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4
SwitchExtension->Segments[ 1 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony)
SwitchExtension->Segments[ 0 ]->RenderLoft( Vert, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2
}
}
}
@@ -2297,17 +2303,17 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
Vert->nz = 0.0;
Vert->u = 0.5;
Vert->v = 0.5;
Vert->x = oxz.x;
Vert->y = oxz.y;
Vert->z = oxz.z;
Vert->x = oxz.x - origin.x;
Vert->y = oxz.y - origin.y;
Vert->z = oxz.z - origin.z;
++Vert;
// ...and add one extra vertex to close the fan...
Vert->nx = 0.0;
Vert->ny = 1.0;
Vert->nz = 0.0;
// mapowanie we współrzędnych scenerii
u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x ) / fTexLength;
v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z ) / ( fTexRatio1 * fTexLength );
u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x + origin.x ) / fTexLength;
v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z + origin.z ) / ( fTexRatio1 * fTexLength );
Vert->u = cosa0 * u + sina0 * v + 0.5;
Vert->v = -sina0 * u + cosa0 * v + 0.5;
Vert->x = SwitchExtension->vPoints[ 0 ].x;
@@ -2321,8 +2327,8 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
Vert->ny = 1.0;
Vert->nz = 0.0;
// mapowanie we współrzędnych scenerii
u = (SwitchExtension->vPoints[i].x - oxz.x) / fTexLength;
v = (SwitchExtension->vPoints[i].z - oxz.z) / (fTexRatio1 * fTexLength);
u = (SwitchExtension->vPoints[i].x - oxz.x + origin.x ) / fTexLength;
v = (SwitchExtension->vPoints[i].z - oxz.z + origin.z ) / (fTexRatio1 * fTexLength);
Vert->u = cosa0 * u + sina0 * v + 0.5;
Vert->v = -sina0 * u + cosa0 * v + 0.5;
Vert->x = SwitchExtension->vPoints[ i ].x;
@@ -2368,7 +2374,7 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
}
if (TextureID1) // jeśli podana była tekstura, generujemy trójkąty
{ // tworzenie trójkątów nawierzchni szosy
Segment->RenderLoft(Vert, bpts1, iTrapezoid ? -2 : 2, fTexLength);
Segment->RenderLoft(Vert, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
}
if (TextureID2)
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w
@@ -2390,13 +2396,13 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
rpts2[3] = vector6(bpts1[3].x, bpts1[3].y, 1.0);
rpts2[4] = vector6(bpts1[3].x - side2, bpts1[3].y, 0.5);
rpts2[5] = vector6(-rozp2, -fTexHeight2, 0.0); // prawy brzeg prawego pobocza
Segment->RenderLoft(Vert, rpts1, -3, fTexLength);
Segment->RenderLoft(Vert, rpts2, -3, fTexLength);
Segment->RenderLoft(Vert, origin, rpts1, -3, fTexLength);
Segment->RenderLoft(Vert, origin, rpts2, -3, fTexLength);
}
else
{ // pobocza zwykłe, brak przechyłki
Segment->RenderLoft(Vert, rpts1, 3, fTexLength);
Segment->RenderLoft(Vert, rpts2, 3, fTexLength);
Segment->RenderLoft(Vert, origin, rpts1, 3, fTexLength);
Segment->RenderLoft(Vert, origin, rpts2, 3, fTexLength);
}
}
}
@@ -2884,13 +2890,14 @@ TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer)
bladesbuffer.data() );
*/
auto bladevertices = bladesbuffer.data();
auto const origin = pMyNode->m_rootposition;
if( SwitchExtension->RightSwitch ) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa
SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 /*, true*/ );
SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 /*, true*/ );
SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 /*, true*/ );
SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 /*, true*/ );
}
else {
SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 /*, true*/ ); // prawa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 /*, true*/ ); // lewa iglica
SwitchExtension->Segments[ 0 ]->RenderLoft( bladevertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 /*, true*/ ); // prawa iglica
SwitchExtension->Segments[ 1 ]->RenderLoft( bladevertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 /*, true*/ ); // lewa iglica
}
// push back updated geometry
::glBufferSubData(

View File

@@ -324,7 +324,7 @@ int TTraction::RaArrayPrepare()
return iLines;
};
int TTraction::RaArrayFill(CVertNormTex *Vert)
int TTraction::RaArrayFill(CVertNormTex *Vert, Math3D::vector3 const &Origin)
{ // wypełnianie tablic VBO
int debugvertexcount{ 0 };
@@ -332,14 +332,14 @@ int TTraction::RaArrayFill(CVertNormTex *Vert)
if (Wires == 2)
WireOffset = 0;
// jezdny
Vert->x = pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
Vert->y = pPoint1.y;
Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
Vert->x = pPoint1.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pPoint1.y - Origin.y;
Vert->z = pPoint1.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
Vert->y = pPoint2.y;
Vert->z = pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
Vert->x = pPoint2.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pPoint2.y - Origin.y;
Vert->z = pPoint2.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
// Nie wiem co 'Marcin
@@ -355,9 +355,9 @@ int TTraction::RaArrayFill(CVertNormTex *Vert)
// Przewod nosny 'Marcin
if (Wires > 1)
{ // lina nośna w kawałkach
Vert->x = pPoint3.x;
Vert->y = pPoint3.y;
Vert->z = pPoint3.z;
Vert->x = pPoint3.x - Origin.x;
Vert->y = pPoint3.y - Origin.y;
Vert->z = pPoint3.z - Origin.z;
++Vert;
++debugvertexcount;
for (int i = 0; i < iNumSections - 1; ++i)
@@ -367,31 +367,31 @@ int TTraction::RaArrayFill(CVertNormTex *Vert)
if( ( Wires < 4 )
|| ( ( i != 0 )
&& ( i != iNumSections - 2 ) ) ) {
Vert->x = pt3.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference;
Vert->z = pt3.z;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
}
f += step;
}
Vert->x = pPoint4.x;
Vert->y = pPoint4.y;
Vert->z = pPoint4.z;
Vert->x = pPoint4.x - Origin.x;
Vert->y = pPoint4.y - Origin.y;
Vert->z = pPoint4.z - Origin.z;
++Vert;
++debugvertexcount;
}
// Drugi przewod jezdny 'Winger
if (Wires > 2)
{
Vert->x = pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
Vert->y = pPoint1.y;
Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
Vert->x = pPoint1.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x;
Vert->y = pPoint1.y - Origin.y;
Vert->z = pPoint1.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset;
Vert->y = pPoint2.y;
Vert->z = pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset;
Vert->x = pPoint2.x + (pPoint2.z / ddp - pPoint1.z / ddp) * WireOffset - Origin.x;
Vert->y = pPoint2.y - Origin.y;
Vert->z = pPoint2.z + (-pPoint2.x / ddp + pPoint1.x / ddp) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
}
@@ -399,28 +399,29 @@ int TTraction::RaArrayFill(CVertNormTex *Vert)
f = step;
if( Wires == 4 ) {
Vert->x = pPoint3.x;
Vert->y = pPoint3.y - 0.65f * fHeightDifference;
Vert->z = pPoint3.z;
Vert->x = pPoint3.x - Origin.x;
Vert->y = pPoint3.y - 0.65f * fHeightDifference - Origin.y;
Vert->z = pPoint3.z - Origin.z;
++Vert;
++debugvertexcount;
for( int i = 0; i < iNumSections - 1; ++i ) {
pt3 = pPoint3 + v1 * f;
t = ( 1 - std::fabs( f - mid ) * 2 );
Vert->x = pt3.x;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - (
( ( i == 0 )
|| ( i == iNumSections - 2 ) ) ?
0.25f * fHeightDifference :
0.05 );
Vert->z = pt3.z;
0.05 )
- Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
f += step;
}
Vert->x = pPoint4.x;
Vert->y = pPoint4.y - 0.65f * fHeightDifference;
Vert->z = pPoint4.z;
Vert->x = pPoint4.x - Origin.x;
Vert->y = pPoint4.y - 0.65f * fHeightDifference - Origin.y;
Vert->z = pPoint4.z - Origin.z;
++Vert;
++debugvertexcount;
}
@@ -439,40 +440,40 @@ int TTraction::RaArrayFill(CVertNormTex *Vert)
t = (1 - std::fabs(f - mid) * 2);
if( ( i % 2 ) == 0 ) {
Vert->x = pt3.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 );
Vert->z = pt3.z;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
Vert->y = pt4.y;
Vert->z = pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
Vert->x = pt4.x - ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pt4.y - Origin.y;
Vert->z = pt4.z - ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
}
else {
Vert->x = pt3.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 );
Vert->z = pt3.z;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - ( ( i == 0 ) || ( i == iNumSections - 2 ) ? flo : flo1 ) - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset;
Vert->y = pt4.y;
Vert->z = pt4.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset;
Vert->x = pt4.x + ( pPoint2.z / ddp - pPoint1.z / ddp ) * WireOffset - Origin.x;
Vert->y = pt4.y - Origin.y;
Vert->z = pt4.z + ( -pPoint2.x / ddp + pPoint1.x / ddp ) * WireOffset - Origin.z;
++Vert;
++debugvertexcount;
}
if( ( ( Wires == 4 )
&& ( ( i == 1 )
|| ( i == iNumSections - 3 ) ) ) ) {
Vert->x = pt3.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05;
Vert->z = pt3.z;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - 0.05 - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
Vert->x = pt3.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference;
Vert->z = pt3.z;
Vert->x = pt3.x - Origin.x;
Vert->y = pt3.y - std::sqrt( t ) * fHeightDifference - Origin.y;
Vert->z = pt3.z - Origin.z;
++Vert;
++debugvertexcount;
}

View File

@@ -68,7 +68,7 @@ class TTraction
// virtual void SelectedRender();
void RenderDL(float mgn);
int RaArrayPrepare();
int RaArrayFill(CVertNormTex *Vert);
int RaArrayFill( CVertNormTex *Vert, Math3D::vector3 const &Origin );
void RenderVBO(float mgn, int iPtr);
int TestPoint(Math3D::vector3 *Point);
void Connect(int my, TTraction *with, int to);

View File

@@ -1276,6 +1276,8 @@ TWorld::Render_Cab() {
return;
}
::glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit
/*
glPushMatrix();
vector3 pos = dynamic->GetPosition(); // wszpółrzędne pojazdu z kabiną
// glTranslatef(pos.x,pos.y,pos.z); //przesunięcie o wektor (tak było i trzęsło)
@@ -1284,7 +1286,11 @@ TWorld::Render_Cab() {
glLoadIdentity(); // zacząć od macierzy jedynkowej
Camera.SetCabMatrix( pos ); // widok z kamery po przesunięciu
glMultMatrixd( dynamic->mMatrix.getArray() ); // ta macierz nie ma przesunięcia
glEnable( GL_LIGHTING ); // po renderowaniu drutów może być to wyłączone. TODO: have the wires render take care of its own shit
*/
::glPushMatrix();
auto const originoffset = dynamic->GetPosition() - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glMultMatrixd( dynamic->mMatrix.getArray() );
if( dynamic->mdKabina ) // bo mogła zniknąć przy przechodzeniu do innego pojazdu
{

View File

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

View File

@@ -142,9 +142,16 @@ opengl_renderer::Render() {
::glLoadIdentity();
if( World.InitPerformed() ) {
/*
World.Camera.SetMatrix();
m_camera.update_frustum();
*/
glm::dmat4 worldcamera;
World.Camera.SetMatrix( worldcamera );
m_camera.update_frustum( OpenGLMatrices.data( GL_PROJECTION ), worldcamera );
// frustum tests are performed in 'world space' but after we set up frustum
// we no longer need camera translation, only rotation
::glMultMatrixd( glm::value_ptr( glm::dmat4( glm::dmat3( worldcamera ))));
Render( &World.Environment );
Render( &World.Ground );
@@ -178,11 +185,12 @@ opengl_renderer::Render( world_environment *Environment ) {
/*
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
*/
/*
glm::mat4 worldcamera;
World.Camera.SetMatrix( worldcamera );
glLoadIdentity();
glMultMatrixf( glm::value_ptr( glm::mat4( glm::mat3( worldcamera ) ) ) );
*/
// setup fog
if( Global::fFogEnd > 0 ) {
// fog setup
@@ -294,12 +302,16 @@ opengl_renderer::Render( world_environment *Environment ) {
bool
opengl_renderer::Render( TGround *Ground ) {
/*
glDisable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
glEnable( GL_LIGHTING );
glColor3f( 1.0f, 1.0f, 1.0f );
::glEnable( GL_LIGHTING );
::glDisable( GL_BLEND );
::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
::glColor3f( 1.0f, 1.0f, 1.0f );
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
Update_Lights( Ground->m_lights );
/*
glm::vec3 const cameraposition( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 );
int const cameraz = static_cast<int>( std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2 );
@@ -317,15 +329,6 @@ opengl_renderer::Render( TGround *Ground ) {
}
}
*/
::glEnable( GL_LIGHTING );
::glDisable( GL_BLEND );
::glAlphaFunc( GL_GREATER, 0.50f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
::glColor3f( 1.0f, 1.0f, 1.0f );
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
Update_Lights( Ground->m_lights );
Ground->CameraDirection.x = std::sin( Global::pCameraRotation ); // wektor kierunkowy
Ground->CameraDirection.z = std::cos( Global::pCameraRotation );
TGroundNode *node;
@@ -354,6 +357,16 @@ opengl_renderer::Render( TGround *Ground ) {
}
}
// renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
// pre-calculate camera view span
double const fieldofviewcosine =
std::cos(
std::max(
// vertical...
Global::FieldOfView / Global::ZoomFactor,
// ...or horizontal, whichever is bigger
Global::FieldOfView / Global::ZoomFactor
* std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ) ) );
Ground->iRendered = 0; // ilość renderowanych sektorów
Math3D::vector3 direction;
for( k = 0; k < Global::iSegmentsRendered; ++k ) // sektory w kolejności odległości
@@ -369,10 +382,16 @@ opengl_renderer::Render( TGround *Ground ) {
if( Math3D::LengthSquared3( direction ) > 5 ) // te blisko są zawsze wyświetlane
{
direction = Math3D::SafeNormalize( direction ); // normalizacja
if( Ground->CameraDirection.x * direction.x + Ground->CameraDirection.z * direction.z < 0.55 )
if( Ground->CameraDirection.x * direction.x + Ground->CameraDirection.z * direction.z < 0.5 )
continue; // pomijanie sektorów poza kątem patrzenia
}
// kwadrat kilometrowy nie zawsze, bo szkoda FPS
// TODO: unify all math objects
::glPushMatrix();
auto const &cellorigin = Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].m_area.center;
auto const originoffset = Math3D::vector3( cellorigin.x, cellorigin.y, cellorigin.z ) - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
if( Global::bUseVBO ) {
// vbo render path
Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].RenderVBO();
@@ -381,6 +400,8 @@ opengl_renderer::Render( TGround *Ground ) {
// display list render path
Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ].RenderDL();
}
::glPopMatrix();
if( ( tmp = Ground->FastGetSubRect( i + c, j + r ) ) != nullptr ) {
if( tmp->iNodeCount ) {
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
@@ -389,16 +410,15 @@ opengl_renderer::Render( TGround *Ground ) {
}
} while( ( i < 0 ) || ( j < 0 ) ); // są 4 przypadki, oprócz i=j=0
}
// dodać renderowanie terenu z E3D - jedno VBO jest używane dla całego modelu, chyba że jest ich więcej
if( Global::bUseVBO ) {
if( Global::pTerrainCompact ) {
Global::pTerrainCompact->TerrainRenderVBO( TGroundRect::iFrameNumber );
}
}
// renderowanie nieprzezroczystych
for( i = 0; i < Ground->iRendered; ++i ) {
if( Global::bUseVBO ) {
// vbo render path
Ground->pRendered[ i ]->RenderVBO();
@@ -408,10 +428,8 @@ opengl_renderer::Render( TGround *Ground ) {
Ground->pRendered[ i ]->RenderDL();
}
}
// regular render takes care of all solid geometry present in the scene, thus we can launch alpha parts render here
return Render_Alpha( Ground );
}
bool
@@ -436,22 +454,30 @@ opengl_renderer::Render( TGroundNode *Node ) {
switch (Node->iType)
{
case TP_TRACK: {
if( Global::bUseVBO && ( Node->iNumVerts <= 0 ) ) {
return false;
}
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// TODO: unify the render code after generic buffers are in place
if( Global::bUseVBO ) {
if( Node->iNumVerts ) {
Node->pTrack->RaRenderVBO( Node->iVboPtr );
}
else {
return false;
}
// vbo render path
Node->pTrack->RaRenderVBO( Node->iVboPtr );
}
else {
// display list render path
Node->pTrack->Render();
}
// post-render cleanup
::glPopMatrix();
return true;
}
case TP_MODEL: {
Node->Model->Render( &Node->pCenter );
Node->Model->Render( Node->pCenter - Global::pCameraPosition );
return true;
}
case TP_MEMCELL: {
@@ -480,6 +506,9 @@ opengl_renderer::Render( TGroundNode *Node ) {
// wszelkie linie są rysowane na samym końcu
if( Node->iNumPts ) {
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
@@ -497,6 +526,9 @@ opengl_renderer::Render( TGroundNode *Node ) {
else {
::glCallList( Node->DisplayListID );
}
// post-render cleanup
::glPopMatrix();
return true;
}
else {
@@ -505,7 +537,17 @@ opengl_renderer::Render( TGroundNode *Node ) {
}
else {
// GL_TRIANGLE etc
if( ( Global::bUseVBO ?
Node->iVboPtr < 0 :
Node->DisplayListID == 0 ) ) {
return false;
}
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glColor3ub(
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
@@ -517,22 +559,16 @@ opengl_renderer::Render( TGroundNode *Node ) {
// 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;
}
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
}
else {
// display list render path
if( Node->DisplayListID != 0 ) {
::glCallList( Node->DisplayListID );
}
else {
return false;
}
::glCallList( Node->DisplayListID );
}
// post-render cleanup
::glPopMatrix();
return true;
}
}
@@ -550,11 +586,11 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
// setup
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
double squaredistance = SquareMagnitude( ( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor );
auto const originoffset = Dynamic->vPosition - Global::pCameraPosition;
double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
::glPushMatrix();
/*
if( Dynamic == Global::pUserDynamic ) {
//specjalne ustawienie, aby nie trzęsło
//tu trzeba by ustawić animacje na modelu zewnętrznym
@@ -563,7 +599,8 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
}
else
::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii
*/
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glMultMatrixd( Dynamic->mMatrix.getArray() );
if( Dynamic->fShade > 0.0f ) {
@@ -666,7 +703,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
if( Angle.z != 0.0 )
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
auto const result = Render( Model, Material, SquareMagnitude( Position - Global::GetCameraPosition() ) );
auto const result = Render( Model, Material, SquareMagnitude( Position / Global::ZoomFactor ) ); // position is effectively camera offset
::glPopMatrix();
@@ -932,12 +969,19 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
case TP_TRACTION: {
// TODO: unify the render code after generic buffers are in place
if( Node->bVisible ) {
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
if( Global::bUseVBO ) {
Node->hvTraction->RenderVBO( distancesquared, Node->iVboPtr );
}
else {
Node->hvTraction->RenderDL( distancesquared );
}
// post-render cleanup
::glPopMatrix();
return true;
}
else {
@@ -945,7 +989,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
}
}
case TP_MODEL: {
Node->Model->RenderAlpha( &Node->pCenter );
Node->Model->RenderAlpha( Node->pCenter - Global::pCameraPosition );
return true;
}
}
@@ -980,6 +1024,9 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// wszelkie linie są rysowane na samym końcu
if( Node->iNumPts ) {
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// w zaleznosci od koloru swiatla
::glColor4ub(
static_cast<GLubyte>( std::floor( Node->Diffuse[ 0 ] * Global::DayLight.ambient[ 0 ] ) ),
@@ -997,12 +1044,18 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
else {
::glCallList( Node->DisplayListID );
}
// post-render cleanup
::glPopMatrix();
result = true;
}
}
else {
// GL_TRIANGLE etc
// setup
::glPushMatrix();
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glColor3ub(
static_cast<GLubyte>( Node->Diffuse[ 0 ] ),
static_cast<GLubyte>( Node->Diffuse[ 1 ] ),
@@ -1024,8 +1077,10 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
::glCallList( Node->DisplayListID );
result = true;
}
// post-render cleanup
::glPopMatrix();
}
// post-render cleanup
#ifdef _PROBLEND
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
{
@@ -1049,17 +1104,19 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
// setup
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
double squaredistance = SquareMagnitude( ( Global::pCameraPosition - Dynamic->vPosition ) / Global::ZoomFactor );
auto const originoffset = Dynamic->vPosition - Global::pCameraPosition;
double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
::glPushMatrix();
/*
if( Dynamic == Global::pUserDynamic ) { // specjalne ustawienie, aby nie trzęsło
::glLoadIdentity(); // zacząć od macierzy jedynkowej
Global::pCamera->SetCabMatrix( Dynamic->vPosition ); // specjalne ustawienie kamery
}
else
::glTranslated( Dynamic->vPosition.x, Dynamic->vPosition.y, Dynamic->vPosition.z ); // standardowe przesunięcie względem początku scenerii
*/
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
::glMultMatrixd( Dynamic->mMatrix.getArray() );
if( Dynamic->fShade > 0.0f ) {
@@ -1161,7 +1218,7 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
if( Angle.z != 0.0 )
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position - Global::GetCameraPosition() ) );
auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position / Global::ZoomFactor ) ); // position is effectively camera offset
::glPopMatrix();
@@ -1400,7 +1457,7 @@ opengl_renderer::Update_Lights( light_array const &Lights ) {
continue;
}
// if the light passed tests so far, it's good enough
renderlight->set_position( scenelight.position );
renderlight->set_position( scenelight.position - Global::pCameraPosition );
renderlight->direction = scenelight.direction;
auto luminance = Global::fLuminance; // TODO: adjust this based on location, e.g. for tunnels

View File

@@ -94,7 +94,7 @@ public:
update_frustum() { m_frustum.calculate(); }
inline
void
update_frustum(glm::mat4 &Projection, glm::mat4 &Modelview) { m_frustum.calculate(Projection, Modelview); }
update_frustum(glm::mat4 const &Projection, glm::mat4 const &Modelview) { m_frustum.calculate(Projection, Modelview); }
bool
visible( bounding_area const &Area ) const;
bool