mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 03:09:18 +02:00
completed unification of render paths
This commit is contained in:
557
Ground.cpp
557
Ground.cpp
@@ -247,82 +247,13 @@ void TGroundNode::InitNormals()
|
||||
}
|
||||
}
|
||||
/*
|
||||
void TGroundNode::RaRenderVBO()
|
||||
{ // renderowanie z domyslnego bufora VBO
|
||||
glColor3ub(Diffuse[0], Diffuse[1], Diffuse[2]);
|
||||
GfxRenderer.Bind( TextureID ); // Ustaw aktywną teksturę
|
||||
glDrawArrays(iType, iVboPtr, iNumVerts); // Narysuj naraz wszystkie trójkąty
|
||||
}
|
||||
*/
|
||||
void TGroundNode::Compile( glm::dvec3 const &Origin, bool const Multiple )
|
||||
{ // tworzenie skompilowanej listy w wyświetlaniu DL
|
||||
if (false == Multiple)
|
||||
{ // obsługa pojedynczej listy
|
||||
if (DisplayListID)
|
||||
Release();
|
||||
if (Global::bManageNodes)
|
||||
{
|
||||
DisplayListID = glGenLists(1);
|
||||
glNewList(DisplayListID, GL_COMPILE);
|
||||
iVersion = Global::iReCompile; // aktualna wersja siatek (do WireFrame)
|
||||
}
|
||||
}
|
||||
if ((iType == GL_LINES) || (iType == GL_LINE_STRIP) || (iType == GL_LINE_LOOP))
|
||||
{
|
||||
glBegin(iType);
|
||||
for (int i = 0; i < iNumPts; ++i)
|
||||
glVertex3dv( glm::value_ptr( Points[i] - Origin ) );
|
||||
glEnd();
|
||||
}
|
||||
else if (iType == GL_TRIANGLE_STRIP || iType == GL_TRIANGLE_FAN || iType == GL_TRIANGLES)
|
||||
{ // jak nie linie, to trójkąty
|
||||
// TODO: eliminate these calls, they're duplicated by setup part in the unified render function
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
::glColor3fv( glm::value_ptr( Diffuse ) );
|
||||
GfxRenderer.Bind(TextureID);
|
||||
#endif
|
||||
glBegin(iType);
|
||||
for (int i = 0; i < iNumVerts; ++i)
|
||||
{
|
||||
glNormal3fv( glm::value_ptr( Vertices[ i ].normal ) );
|
||||
glTexCoord2fv( glm::value_ptr( Vertices[ i ].texture ) );
|
||||
glVertex3dv( glm::value_ptr( Vertices[ i ].position - Origin ) );
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
/*
|
||||
else if (iType == TP_MESH)
|
||||
{ // grupa ze wspólną teksturą - wrzucanie do wspólnego Display List
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
if (TextureID)
|
||||
GfxRenderer.Bind(TextureID); // Ustaw aktywną teksturę
|
||||
#endif
|
||||
TGroundNode *n = nNode;
|
||||
while (n ? n->TextureID == TextureID : false)
|
||||
{ // wszystkie obiekty o tej samej testurze
|
||||
switch (n->iType)
|
||||
{ // poszczególne typy różnie się tworzy
|
||||
case TP_TRACK:
|
||||
case TP_DUMMYTRACK:
|
||||
n->pTrack->Compile(TextureID); // dodanie trójkątów dla podanej tekstury
|
||||
break;
|
||||
}
|
||||
n = n->nNext3; // następny z listy
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (false == Multiple)
|
||||
if (Global::bManageNodes)
|
||||
glEndList();
|
||||
};
|
||||
|
||||
void TGroundNode::Release()
|
||||
{
|
||||
if (DisplayListID)
|
||||
glDeleteLists(DisplayListID, 1);
|
||||
DisplayListID = 0;
|
||||
};
|
||||
|
||||
*/
|
||||
void TGroundNode::RenderHidden()
|
||||
{ // renderowanie obiektów niewidocznych
|
||||
double mgn = SquareMagnitude(pCenter - Global::pCameraPosition);
|
||||
@@ -354,8 +285,10 @@ void TGroundNode::RenderHidden()
|
||||
//------------------------------------------------------------------------------
|
||||
TSubRect::~TSubRect()
|
||||
{
|
||||
/*
|
||||
if (Global::bManageNodes) // Ra: tu się coś sypie
|
||||
ResourceManager::Unregister(this); // wyrejestrowanie ze sprzątacza
|
||||
*/
|
||||
// TODO: usunąć obiekty z listy (nRootMesh), bo są one tworzone dla sektora
|
||||
delete[] tTracks;
|
||||
}
|
||||
@@ -393,46 +326,22 @@ void TSubRect::NodeAdd(TGroundNode *Node)
|
||||
Node->pTrack->RaOwnerSet(this); // do którego sektora ma zgłaszać animację
|
||||
// NOTE: track merge/sort temporarily disabled to simplify unification of render code
|
||||
// TODO: refactor sorting as universal part of drawing process in the renderer
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
if( Global::bUseVBO ) {
|
||||
Node->nNext3 = nRenderRect;
|
||||
nRenderRect = Node;
|
||||
} // VBO: do nieprzezroczystych z sektora
|
||||
else {
|
||||
Node->nNext3 = nRender;
|
||||
nRender = Node;
|
||||
} // DL: do nieprzezroczystych
|
||||
#else
|
||||
Node->nNext3 = nRenderRect;
|
||||
nRenderRect = Node;
|
||||
#endif
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
case GL_TRIANGLE_FAN:
|
||||
case GL_TRIANGLES:
|
||||
// Node->nNext3=nMeshed; nMeshed=Node; //do podzielenia potem
|
||||
if (Node->iFlags & 0x20) // czy jest przezroczyste?
|
||||
{
|
||||
if (Node->iFlags & 0x20) {
|
||||
// do przezroczystych z sektora
|
||||
Node->nNext3 = nRenderRectAlpha;
|
||||
nRenderRectAlpha = Node;
|
||||
} // DL: do przezroczystych z sektora
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
else if (Global::bUseVBO)
|
||||
{
|
||||
Node->nNext3 = nRenderRect;
|
||||
nRenderRect = Node;
|
||||
} // VBO: do nieprzezroczystych z sektora
|
||||
else
|
||||
{
|
||||
Node->nNext3 = nRender;
|
||||
nRender = Node;
|
||||
} // DL: do nieprzezroczystych wszelakich
|
||||
#else
|
||||
}
|
||||
else {
|
||||
// do nieprzezroczystych z sektora
|
||||
Node->nNext3 = nRenderRect;
|
||||
nRenderRect = Node;
|
||||
} // do nieprzezroczystych z sektora
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case TP_TRACTION:
|
||||
case GL_LINES:
|
||||
@@ -471,9 +380,11 @@ void TSubRect::NodeAdd(TGroundNode *Node)
|
||||
case TP_DYNAMIC:
|
||||
return; // tych nie dopisujemy wcale
|
||||
}
|
||||
Node->nNext2 = nRootNode; // dopisanie do ogólnej listy
|
||||
// dopisanie do ogólnej listy
|
||||
Node->nNext2 = nRootNode;
|
||||
nRootNode = Node;
|
||||
++iNodeCount; // licznik obiektów
|
||||
// licznik obiektów
|
||||
++iNodeCount;
|
||||
}
|
||||
|
||||
// przygotowanie sektora do renderowania
|
||||
@@ -516,8 +427,10 @@ TTrack * TSubRect::FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude)
|
||||
|
||||
bool TSubRect::RaTrackAnimAdd(TTrack *t)
|
||||
{ // aktywacja animacji torów w VBO (zwrotnica, obrotnica)
|
||||
if (m_nVertexCount < 0)
|
||||
return true; // nie ma animacji, gdy nie widać
|
||||
if( false == m_geometrycreated ) {
|
||||
// nie ma animacji, gdy nie widać
|
||||
return true;
|
||||
}
|
||||
if (tTrackAnim)
|
||||
tTrackAnim->RaAnimListAdd(t);
|
||||
else
|
||||
@@ -531,22 +444,7 @@ void TSubRect::RaAnimate()
|
||||
// nie ma nic do animowania
|
||||
return;
|
||||
}
|
||||
// crude way to mark whether a vbo is bound, for the vbo render path
|
||||
// TODO: sort this shit out and re-arrange into something more elegant... eventually
|
||||
GLuint vertexbuffer { static_cast<GLuint>(-1) };
|
||||
if (Global::bUseVBO) {
|
||||
// odświeżenie VBO sektora
|
||||
if( GLEW_VERSION_1_5 ) {
|
||||
// modyfikacje VBO są dostępne od OpenGL 1.5
|
||||
vertexbuffer = m_nVBOVertices;
|
||||
::glBindBuffer( GL_ARRAY_BUFFER, vertexbuffer );
|
||||
}
|
||||
else {
|
||||
// dla OpenGL 1.4 z GL_ARB_vertex_buffer_object odświeżenie całego sektora
|
||||
Release(); // opróżnienie VBO sektora, aby się odświeżył z nowymi ustawieniami
|
||||
}
|
||||
}
|
||||
tTrackAnim = tTrackAnim->RaAnimate( vertexbuffer ); // przeliczenie animacji kolejnego
|
||||
tTrackAnim = tTrackAnim->RaAnimate(); // przeliczenie animacji kolejnego
|
||||
};
|
||||
|
||||
TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude)
|
||||
@@ -562,126 +460,69 @@ TTraction * TSubRect::FindTraction(glm::dvec3 const &Point, int &iConnection, TT
|
||||
return NULL;
|
||||
};
|
||||
|
||||
void TSubRect::LoadNodes()
|
||||
{ // utworzenie siatek VBO dla wszystkich node w sektorze
|
||||
if (m_nVertexCount >= 0)
|
||||
return; // obiekty były już sprawdzone
|
||||
m_nVertexCount = 0; //-1 oznacza, że nie sprawdzono listy obiektów
|
||||
if (!nRootNode)
|
||||
// utworzenie siatek VBO dla wszystkich node w sektorze
|
||||
void TSubRect::LoadNodes() {
|
||||
|
||||
if( true == m_geometrycreated ) {
|
||||
// obiekty były już sprawdzone
|
||||
return;
|
||||
TGroundNode *n = nRootNode;
|
||||
while (n)
|
||||
{
|
||||
switch (n->iType)
|
||||
{
|
||||
case GL_TRIANGLE_STRIP:
|
||||
case GL_TRIANGLE_FAN:
|
||||
case GL_TRIANGLES:
|
||||
n->iVboPtr = m_nVertexCount; // nowy początek
|
||||
m_nVertexCount += n->iNumVerts;
|
||||
break;
|
||||
case GL_LINES:
|
||||
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...
|
||||
break;
|
||||
case TP_TRACK:
|
||||
n->iVboPtr = m_nVertexCount; // nowy początek
|
||||
n->iNumVerts = n->pTrack->RaArrayPrepare(); // zliczenie wierzchołków
|
||||
m_nVertexCount += n->iNumVerts;
|
||||
break;
|
||||
case TP_TRACTION:
|
||||
n->hvTraction->create_geometry( m_geometrybank, n->m_rootposition );
|
||||
break;
|
||||
}
|
||||
n = n->nNext2; // następny z sektora
|
||||
}
|
||||
if (m_nVertexCount <= 0)
|
||||
return; // jeśli nie ma obiektów do wyświetlenia z VBO, to koniec
|
||||
if (Global::bUseVBO)
|
||||
{ // tylko liczenie wierzchołów, gdy nie ma VBO
|
||||
else {
|
||||
// mark it done for future checks
|
||||
m_geometrycreated = true;
|
||||
}
|
||||
|
||||
MakeArray(m_nVertexCount);
|
||||
|
||||
n = nRootNode;
|
||||
int i;
|
||||
while (n)
|
||||
{
|
||||
if (n->iVboPtr >= 0)
|
||||
switch (n->iType)
|
||||
{
|
||||
case GL_TRIANGLE_STRIP:
|
||||
case GL_TRIANGLE_FAN:
|
||||
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 ].position = n->Vertices[ i ].position - n->m_rootposition;
|
||||
/*
|
||||
m_pVNT[n->iVboPtr + i].x = n->Vertices[i].position.x - n->m_rootposition.x;
|
||||
m_pVNT[n->iVboPtr + i].y = n->Vertices[i].position.y - n->m_rootposition.y;
|
||||
m_pVNT[n->iVboPtr + i].z = n->Vertices[i].position.z - n->m_rootposition.z;
|
||||
*/
|
||||
m_pVNT[ n->iVboPtr + i ].normal = n->Vertices[ i ].normal;
|
||||
/*
|
||||
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;
|
||||
*/
|
||||
m_pVNT[ n->iVboPtr + i ].texture = n->Vertices[ i ].texture;
|
||||
/*
|
||||
m_pVNT[n->iVboPtr + i].u = n->Vertices[i].tu;
|
||||
m_pVNT[n->iVboPtr + i].v = n->Vertices[i].tv;
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case GL_LINES:
|
||||
case GL_LINE_STRIP:
|
||||
case GL_LINE_LOOP:
|
||||
for (i = 0; i < n->iNumPts; ++i)
|
||||
{
|
||||
m_pVNT[ n->iVboPtr + i ].position = ( n->Points[ i ] - n->m_rootposition );
|
||||
/*
|
||||
glm::vec3(
|
||||
n->Points[ i ].x - n->m_rootposition.x,
|
||||
n->Points[ i ].y - n->m_rootposition.y,
|
||||
n->Points[ i ].z - n->m_rootposition.z );
|
||||
*/
|
||||
// miejsce w tablicach normalnych i teksturowania się marnuje...
|
||||
}
|
||||
break;
|
||||
case TP_TRACK:
|
||||
if( n->iNumVerts ) { // bo tory zabezpieczające są niewidoczne
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
n->pTrack->RaArrayFill( m_pVNT + n->iVboPtr, m_pVNT, std::min( n->iNumVerts, m_nVertexCount - n->iVboPtr ) );
|
||||
#else
|
||||
n->pTrack->RaArrayFill( m_pVNT.data() + n->iVboPtr, m_pVNT.data(), std::min( n->iNumVerts, m_nVertexCount - n->iVboPtr ) );
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
auto *node { nRootNode };
|
||||
while( node != nullptr ) {
|
||||
switch (node->iType) {
|
||||
case GL_TRIANGLES: {
|
||||
vertex_array vertices;
|
||||
for( std::size_t idx = 0; idx < node->iNumVerts; ++idx ) {
|
||||
vertices.emplace_back(
|
||||
node->Vertices[ idx ].position - node->m_rootposition,
|
||||
node->Vertices[ idx ].normal,
|
||||
node->Vertices[ idx ].texture );
|
||||
}
|
||||
n = n->nNext2; // następny z sektora
|
||||
node->m_geometry = GfxRenderer.Insert( vertices, m_geometrybank, GL_TRIANGLES );
|
||||
SafeDeleteArray( node->Vertices );
|
||||
node->iNumVerts = 0;
|
||||
break;
|
||||
}
|
||||
case GL_LINES: {
|
||||
vertex_array vertices;
|
||||
for( std::size_t idx = 0; idx < node->iNumPts; ++idx ) {
|
||||
vertices.emplace_back(
|
||||
node->Points[ idx ] - node->m_rootposition,
|
||||
glm::vec3(),
|
||||
glm::vec2() );
|
||||
}
|
||||
node->m_geometry = GfxRenderer.Insert( vertices, m_geometrybank, GL_LINES );
|
||||
SafeDeleteArray( node->Vertices );
|
||||
node->iNumPts = 0;
|
||||
break;
|
||||
}
|
||||
case TP_TRACK:
|
||||
if( node->pTrack->bVisible ) { // bo tory zabezpieczające są niewidoczne
|
||||
node->pTrack->create_geometry( m_geometrybank );
|
||||
}
|
||||
break;
|
||||
case TP_TRACTION:
|
||||
node->hvTraction->create_geometry( m_geometrybank, node->m_rootposition );
|
||||
break;
|
||||
default: { break; }
|
||||
}
|
||||
BuildVBOs();
|
||||
node = node->nNext2; // następny z sektora
|
||||
}
|
||||
/*
|
||||
if (Global::bManageNodes)
|
||||
ResourceManager::Register(this); // dodanie do automatu zwalniającego pamięć
|
||||
*/
|
||||
}
|
||||
|
||||
bool TSubRect::StartVBO()
|
||||
{ // początek rysowania elementów z VBO w sektorze
|
||||
SetLastUsage(Timer::GetSimulationTime()); // te z tyłu będą niepotrzebnie zwalniane
|
||||
return CMesh::StartVBO();
|
||||
};
|
||||
|
||||
/*
|
||||
void TSubRect::Release()
|
||||
{ // wirtualne zwolnienie zasobów przez sprzątacz albo destruktor
|
||||
if (Global::bUseVBO)
|
||||
CMesh::Clear(); // usuwanie buforów
|
||||
};
|
||||
|
||||
*/
|
||||
void TSubRect::RenderSounds()
|
||||
{ // aktualizacja dźwięków w pojazdach sektora (sektor może nie być wyświetlany)
|
||||
for (int j = 0; j < iTracks; ++j)
|
||||
@@ -708,7 +549,7 @@ TGroundRect::Init() {
|
||||
float const subrectsize = 1000.0f / iNumSubRects;
|
||||
for( int column = 0; column < iNumSubRects; ++column ) {
|
||||
for( int row = 0; row < iNumSubRects; ++row ) {
|
||||
auto subcell = FastGetRect( column, row );
|
||||
auto subcell = FastGetSubRect( column, row );
|
||||
auto &area = subcell->m_area;
|
||||
area.center =
|
||||
m_area.center
|
||||
@@ -734,8 +575,9 @@ TGround::TGround()
|
||||
nRootOfType[ i ] = nullptr; // zerowanie tablic wyszukiwania
|
||||
}
|
||||
::SecureZeroMemory( TempConnectionType, sizeof( TempConnectionType ) );
|
||||
/*
|
||||
::SecureZeroMemory( pRendered, sizeof( pRendered ) );
|
||||
|
||||
*/
|
||||
// set bounding area information for ground rectangles
|
||||
float const rectsize = 1000.0f;
|
||||
glm::vec3 const worldcenter;
|
||||
@@ -876,9 +718,9 @@ void TGround::RaTriangleDivider(TGroundNode *node)
|
||||
return; // tylko pojedyncze trójkąty
|
||||
if (node->iNumVerts != 3)
|
||||
return; // tylko gdy jeden trójkąt
|
||||
double x0 = 1000.0 * floor(0.001 * node->pCenter.x) - 200.0;
|
||||
double x0 = 1000.0 * std::floor(0.001 * node->pCenter.x) - 200.0;
|
||||
double x1 = x0 + 1400.0;
|
||||
double z0 = 1000.0 * floor(0.001 * node->pCenter.z) - 200.0;
|
||||
double z0 = 1000.0 * std::floor(0.001 * node->pCenter.z) - 200.0;
|
||||
double z1 = z0 + 1400.0;
|
||||
if ((node->Vertices[0].position.x >= x0) && (node->Vertices[0].position.x <= x1) &&
|
||||
(node->Vertices[0].position.z >= z0) && (node->Vertices[0].position.z <= z1) &&
|
||||
@@ -999,7 +841,6 @@ void TGround::RaTriangleDivider(TGroundNode *node)
|
||||
TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
{ // wczytanie wpisu typu "node"
|
||||
std::string str, str1, str2, str3, str4, Skin, DriverType, asNodeName;
|
||||
int nv, i;
|
||||
double tf, r, rmin, tf1, tf3;
|
||||
int int1;
|
||||
size_t int2;
|
||||
@@ -1415,7 +1256,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
tmp->nNode[0].iType = TP_MODEL; // pierwszy zawiera model (dla delete)
|
||||
tmp->nNode[0].Model = Global::pTerrainCompact;
|
||||
tmp->nNode[0].iFlags = 0x200; // nie wyświetlany, ale usuwany
|
||||
for (i = 1; i < tmp->iCount; ++i)
|
||||
for (std::size_t i = 1; i < tmp->iCount; ++i)
|
||||
{ // a reszta to submodele
|
||||
tmp->nNode[i].iType = TP_SUBMODEL; //
|
||||
tmp->nNode[i].smTerrain = Global::pTerrainCompact->TerrainSquare(i - 1);
|
||||
@@ -1498,19 +1339,20 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
#endif
|
||||
tmp->TextureID = GfxRenderer.GetTextureId( str, szTexturePath );
|
||||
tmp->iFlags = GfxRenderer.Texture(tmp->TextureID).has_alpha ? 0x220 : 0x210; // z usuwaniem
|
||||
if (((tmp->iType == GL_TRIANGLES) && (tmp->iFlags & 0x10)) ?
|
||||
Global::pTerrainCompact->TerrainLoaded() :
|
||||
false)
|
||||
{ // jeśli jest tekstura nieprzezroczysta, a teren załadowany, to pomijamy trójkąty
|
||||
do
|
||||
{ // pomijanie trójkątów
|
||||
if( (tmp->iType == GL_TRIANGLES)
|
||||
&& (tmp->iFlags & 0x10)
|
||||
&& (Global::pTerrainCompact->TerrainLoaded()) ) {
|
||||
// jeśli jest tekstura nieprzezroczysta, a teren załadowany, to pomijamy trójkąty
|
||||
do {
|
||||
// pomijanie trójkątów
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
} while (token.compare("endtri") != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TGroundVertex vertex;
|
||||
TGroundVertex vertex, vertex1, vertex2;
|
||||
std::size_t vertexcount { 0 };
|
||||
do {
|
||||
parser->getTokens( 8, false );
|
||||
*parser
|
||||
@@ -1522,14 +1364,6 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
>> vertex.normal.z
|
||||
>> vertex.texture.s
|
||||
>> vertex.texture.t;
|
||||
/*
|
||||
vertex.position.RotateZ( aRotate.z / 180 * M_PI );
|
||||
vertex.position.RotateX( aRotate.x / 180 * M_PI );
|
||||
vertex.position.RotateY( aRotate.y / 180 * M_PI );
|
||||
vertex.normal.RotateZ( aRotate.z / 180 * M_PI );
|
||||
vertex.normal.RotateX( aRotate.x / 180 * M_PI );
|
||||
vertex.normal.RotateY( aRotate.y / 180 * M_PI );
|
||||
*/
|
||||
vertex.position = glm::rotateZ( vertex.position, aRotate.z / 180 * M_PI );
|
||||
vertex.position = glm::rotateX( vertex.position, aRotate.x / 180 * M_PI );
|
||||
vertex.position = glm::rotateY( vertex.position, aRotate.y / 180 * M_PI );
|
||||
@@ -1538,19 +1372,52 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
vertex.normal = glm::rotateY( vertex.normal, static_cast<float>( aRotate.y / 180 * M_PI ) );
|
||||
vertex.position += glm::dvec3( pOrigin.x, pOrigin.y, pOrigin.z );
|
||||
tmp->pCenter += vertex.position;
|
||||
|
||||
importedvertices.emplace_back( vertex );
|
||||
// convert all data to gl_triangles to allow data merge for matching nodes
|
||||
switch( tmp->iType ) {
|
||||
case GL_TRIANGLES: {
|
||||
importedvertices.emplace_back( vertex );
|
||||
break;
|
||||
}
|
||||
case GL_TRIANGLE_FAN: {
|
||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||
else if( vertexcount >= 2 ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex2 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
vertex2 = vertex;
|
||||
}
|
||||
++vertexcount;
|
||||
break;
|
||||
}
|
||||
case GL_TRIANGLE_STRIP: {
|
||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||
else if( vertexcount >= 2 ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex2 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
vertex1 = vertex2;
|
||||
vertex2 = vertex;
|
||||
}
|
||||
++vertexcount;
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
|
||||
} while (token.compare("endtri") != 0);
|
||||
|
||||
nv = (int)importedvertices.size();
|
||||
tmp->iType = GL_TRIANGLES;
|
||||
|
||||
auto const nv = importedvertices.size();
|
||||
tmp->Init(nv); // utworzenie tablicy wierzchołków
|
||||
tmp->pCenter /= (nv > 0 ? nv : 1);
|
||||
|
||||
r = 0;
|
||||
for (int i = 0; i < nv; i++)
|
||||
for (std::size_t i = 0; i < nv; ++i)
|
||||
{
|
||||
tmp->Vertices[i] = importedvertices[i];
|
||||
tf = SquareMagnitude( tmp->Vertices[ i ].position - tmp->pCenter );
|
||||
@@ -1571,8 +1438,10 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
>> tmp->Diffuse.b
|
||||
>> tmp->fLineThickness;
|
||||
tmp->Diffuse /= 255.0f;
|
||||
TGroundVertex vertex;
|
||||
i = 0;
|
||||
|
||||
TGroundVertex vertex, vertex0, vertex1;
|
||||
std::size_t vertexcount{ 0 };
|
||||
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
do {
|
||||
@@ -1581,32 +1450,64 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
||||
*parser
|
||||
>> vertex.position.y
|
||||
>> vertex.position.z;
|
||||
/*
|
||||
vertex.position.RotateZ( aRotate.z / 180 * M_PI );
|
||||
vertex.position.RotateX( aRotate.x / 180 * M_PI );
|
||||
vertex.position.RotateY( aRotate.y / 180 * M_PI );
|
||||
*/
|
||||
vertex.position = glm::rotateZ( vertex.position, aRotate.z / 180 * M_PI );
|
||||
vertex.position = glm::rotateX( vertex.position, aRotate.x / 180 * M_PI );
|
||||
vertex.position = glm::rotateY( vertex.position, aRotate.y / 180 * M_PI );
|
||||
|
||||
vertex.position += glm::dvec3( pOrigin.x, pOrigin.y, pOrigin.z );
|
||||
|
||||
tmp->pCenter += vertex.position;
|
||||
|
||||
importedvertices.emplace_back( vertex );
|
||||
|
||||
++i;
|
||||
// convert all data to gl_lines to allow data merge for matching nodes
|
||||
switch( tmp->iType ) {
|
||||
case GL_LINES: {
|
||||
importedvertices.emplace_back( vertex );
|
||||
break;
|
||||
}
|
||||
case GL_LINE_STRIP: {
|
||||
if( vertexcount > 0 ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
}
|
||||
vertex1 = vertex;
|
||||
++vertexcount;
|
||||
break;
|
||||
}
|
||||
case GL_LINE_LOOP: {
|
||||
if( vertexcount == 0 ) {
|
||||
vertex0 = vertex;
|
||||
vertex1 = vertex;
|
||||
}
|
||||
else {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
}
|
||||
vertex1 = vertex;
|
||||
++vertexcount;
|
||||
break;
|
||||
}
|
||||
default: { break; }
|
||||
}
|
||||
parser->getTokens();
|
||||
*parser >> token;
|
||||
} while( token.compare( "endline" ) != 0 );
|
||||
nv = i;
|
||||
// tmp->Init(nv);
|
||||
// add closing line for the loop
|
||||
if( ( tmp->iType == GL_LINE_LOOP )
|
||||
&& ( vertexcount > 2 ) ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex0 );
|
||||
}
|
||||
if( importedvertices.size() % 2 != 0 ) {
|
||||
ErrorLog( "Lines node specified odd number of vertices, encountered in file \"" + parser->Name() + "\"" );
|
||||
importedvertices.pop_back();
|
||||
}
|
||||
tmp->iType = GL_LINES;
|
||||
|
||||
auto const nv = importedvertices.size();
|
||||
tmp->Points = new glm::dvec3[ nv ];
|
||||
tmp->iNumPts = nv;
|
||||
tmp->pCenter /= ( nv > 0 ? nv : 1 );
|
||||
for( int i = 0; i < nv; i++ )
|
||||
for( std::size_t i = 0; i < nv; ++i ) {
|
||||
tmp->Points[ i ] = importedvertices[ i ].position;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1622,7 +1523,7 @@ TSubRect * TGround::FastGetSubRect(int iCol, int iRow)
|
||||
sc = iCol - bc * iNumSubRects;
|
||||
if ((br < 0) || (bc < 0) || (br >= iNumRects) || (bc >= iNumRects))
|
||||
return NULL;
|
||||
return (Rects[bc][br].FastGetRect(sc, sr));
|
||||
return (Rects[bc][br].FastGetSubRect(sc, sr));
|
||||
}
|
||||
|
||||
TSubRect * TGround::GetSubRect(int iCol, int iRow)
|
||||
@@ -1634,7 +1535,7 @@ TSubRect * TGround::GetSubRect(int iCol, int iRow)
|
||||
sc = iCol - bc * iNumSubRects;
|
||||
if ((br < 0) || (bc < 0) || (br >= iNumRects) || (bc >= iNumRects))
|
||||
return NULL; // jeśli poza mapą
|
||||
return (Rects[bc][br].SafeGetRect(sc, sr)); // pobranie małego kwadratu
|
||||
return (Rects[bc][br].SafeGetSubRect(sc, sr)); // pobranie małego kwadratu
|
||||
}
|
||||
|
||||
TEvent * TGround::FindEvent(const std::string &asEventName)
|
||||
@@ -1670,23 +1571,21 @@ void TGround::FirstInit()
|
||||
return; // Ra: żeby nie robiło się dwa razy
|
||||
bInitDone = true;
|
||||
WriteLog("InitNormals");
|
||||
int i, j;
|
||||
for (i = 0; i < TP_LAST; ++i)
|
||||
{
|
||||
for (TGroundNode *Current = nRootOfType[i]; Current; Current = Current->nNext)
|
||||
{
|
||||
for (int type = 0; type < TP_LAST; ++type) {
|
||||
for (TGroundNode *Current = nRootOfType[type]; Current != nullptr; Current = Current->nNext) {
|
||||
|
||||
Current->InitNormals();
|
||||
if (Current->iType != TP_DYNAMIC)
|
||||
{ // pojazdów w ogóle nie dotyczy dodawanie do mapy
|
||||
if( ( i == TP_EVLAUNCH )
|
||||
if( ( type == TP_EVLAUNCH )
|
||||
&& ( true == Current->EvLaunch->IsGlobal() ) ) {
|
||||
// dodanie do globalnego obiektu
|
||||
srGlobal.NodeAdd( Current );
|
||||
}
|
||||
else if (i == TP_TERRAIN)
|
||||
else if (type == TP_TERRAIN)
|
||||
{ // specjalne przetwarzanie terenu wczytanego z pliku E3D
|
||||
TGroundRect *gr;
|
||||
for (j = 1; j < Current->iCount; ++j)
|
||||
for (int j = 1; j < Current->iCount; ++j)
|
||||
{ // od 1 do końca są zestawy trójkątów
|
||||
std::string xxxzzz = Current->nNode[j].smTerrain->pName; // pobranie nazwy
|
||||
gr = GetRect(
|
||||
@@ -1706,6 +1605,7 @@ void TGround::FirstInit()
|
||||
// dodajemy do kwadratu kilometrowego
|
||||
// override visibility ranges, to ensure the content is drawn from far enough
|
||||
// TODO: subclass NodeAdd() for the ground cell and specialize it, instead of this
|
||||
// TODO: given their view ranges are the same, combine the geometry in single per-material nodes
|
||||
Current->fSquareRadius = 50000.0 * 50000.0;
|
||||
Current->fSquareMinRadius = 0.0;
|
||||
GetRect( Current->pCenter.x, Current->pCenter.z )->NodeAdd( Current );
|
||||
@@ -1713,8 +1613,8 @@ void TGround::FirstInit()
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < iNumRects; ++i)
|
||||
for (j = 0; j < iNumRects; ++j)
|
||||
for (std::size_t i = 0; i < iNumRects; ++i)
|
||||
for (std::size_t j = 0; j < iNumRects; ++j)
|
||||
Rects[i][j].Optimize(); // optymalizacja obiektów w sektorach
|
||||
|
||||
WriteLog("InitNormals OK");
|
||||
@@ -1751,7 +1651,7 @@ bool TGround::Init(std::string File)
|
||||
|
||||
std::stack<Math3D::vector3> OriginStack; // stos zagnieżdżenia origin
|
||||
|
||||
TGroundNode *LastNode = NULL; // do użycia w trainset
|
||||
TGroundNode *LastNode = nullptr; // do użycia w trainset
|
||||
iNumNodes = 0;
|
||||
token = "";
|
||||
parser.getTokens();
|
||||
@@ -1763,64 +1663,76 @@ bool TGround::Init(std::string File)
|
||||
++processed;
|
||||
if( processed % 1000 == 0 )
|
||||
{
|
||||
glfwPollEvents();
|
||||
UILayer.set_progress( parser.getProgress(), parser.getFullProgress() );
|
||||
GfxRenderer.Render();
|
||||
glfwPollEvents();
|
||||
}
|
||||
str = token;
|
||||
if (str == "node")
|
||||
{
|
||||
LastNode = AddGroundNode(&parser); // rozpoznanie węzła
|
||||
if (LastNode)
|
||||
{ // jeżeli przetworzony poprawnie
|
||||
if (LastNode->iType == GL_TRIANGLES)
|
||||
{
|
||||
if (!LastNode->Vertices)
|
||||
SafeDelete(LastNode); // usuwamy nieprzezroczyste trójkąty terenu
|
||||
}
|
||||
else if( ( LastNode->iType == TP_TRACTION )
|
||||
&& ( false == Global::bLoadTraction ) ) {
|
||||
SafeDelete( LastNode ); // usuwamy druty, jeśli wyłączone
|
||||
if (str == "node") {
|
||||
// rozpoznanie węzła
|
||||
LastNode = AddGroundNode(&parser);
|
||||
if (LastNode) {
|
||||
// jeżeli przetworzony poprawnie
|
||||
switch( LastNode->iType ) {
|
||||
// validate the new node
|
||||
case GL_TRIANGLES: {
|
||||
if( LastNode->Vertices == nullptr ) {
|
||||
SafeDelete( LastNode );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TP_TRACTION: {
|
||||
if( false == Global::bLoadTraction ) {
|
||||
// usuwamy druty, jeśli wyłączone
|
||||
SafeDelete( LastNode );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (LastNode) // dopiero na koniec dopisujemy do tablic
|
||||
if (LastNode->iType != TP_DYNAMIC)
|
||||
{ // jeśli nie jest pojazdem
|
||||
// ostatni dodany dołączamy na końcu nowego
|
||||
LastNode->nNext = nRootOfType[LastNode->iType];
|
||||
if( LastNode ) {
|
||||
// dopiero na koniec dopisujemy do tablic
|
||||
if( LastNode->iType != TP_DYNAMIC ) {
|
||||
// jeśli nie jest pojazdem ostatni dodany dołączamy na końcu nowego
|
||||
LastNode->nNext = nRootOfType[ LastNode->iType ];
|
||||
// ustawienie nowego na początku listy
|
||||
nRootOfType[LastNode->iType] = LastNode;
|
||||
iNumNodes++;
|
||||
nRootOfType[ LastNode->iType ] = LastNode;
|
||||
++iNumNodes;
|
||||
}
|
||||
else
|
||||
{ // jeśli jest pojazdem
|
||||
// if (!bInitDone) FirstInit(); //jeśli nie było w scenerii
|
||||
if (LastNode->DynamicObject->Mechanik) // ale może być pasażer
|
||||
if (LastNode->DynamicObject->Mechanik
|
||||
->Primary()) // jeśli jest głównym (pasażer nie jest)
|
||||
nTrainSetDriver =
|
||||
LastNode; // pojazd, któremu zostanie wysłany rozkład
|
||||
else { // jeśli jest pojazdem
|
||||
if( ( LastNode->DynamicObject->Mechanik != nullptr )
|
||||
&& ( LastNode->DynamicObject->Mechanik->Primary() ) ) {
|
||||
// jeśli jest głównym (pasażer nie jest)
|
||||
nTrainSetDriver = LastNode; // pojazd, któremu zostanie wysłany rozkład
|
||||
}
|
||||
LastNode->nNext = nRootDynamic;
|
||||
nRootDynamic = LastNode; // dopisanie z przodu do listy
|
||||
// if (bTrainSet && (LastNode?(LastNode->iType==TP_DYNAMIC):false))
|
||||
if (nTrainSetNode) // jeżeli istnieje wcześniejszy TP_DYNAMIC
|
||||
|
||||
if( nTrainSetNode != nullptr ) {
|
||||
// jeżeli istnieje wcześniejszy TP_DYNAMIC
|
||||
nTrainSetNode->DynamicObject->AttachPrev(
|
||||
LastNode->DynamicObject,
|
||||
TempConnectionType[iTrainSetWehicleNumber - 2]);
|
||||
TempConnectionType[ iTrainSetWehicleNumber - 2 ] );
|
||||
}
|
||||
nTrainSetNode = LastNode; // ostatnio wczytany
|
||||
if (TempConnectionType[iTrainSetWehicleNumber - 1] ==
|
||||
0) // jeśli sprzęg jest zerowy, to wysłać rozkład do składu
|
||||
|
||||
if( TempConnectionType[ iTrainSetWehicleNumber - 1 ] == 0 ) // jeśli sprzęg jest zerowy, to wysłać rozkład do składu
|
||||
{ // powinien też tu wchodzić, gdy pojazd bez trainset
|
||||
if (nTrainSetDriver) // pojazd, któremu zostanie wysłany rozkład
|
||||
if( nTrainSetDriver ) // pojazd, któremu zostanie wysłany rozkład
|
||||
{ // wysłanie komendy "Timetable" ustawia odpowiedni tryb jazdy
|
||||
nTrainSetDriver->DynamicObject->Mechanik->DirectionInitial();
|
||||
nTrainSetDriver->DynamicObject->Mechanik->PutCommand(
|
||||
"Timetable:" + asTrainName, fTrainSetVel, 0, NULL);
|
||||
nTrainSetDriver =
|
||||
NULL; // a przy "endtrainset" już wtedy nie potrzeba
|
||||
"Timetable:" + asTrainName,
|
||||
fTrainSetVel, 0,
|
||||
nullptr );
|
||||
nTrainSetDriver = nullptr; // a przy "endtrainset" już wtedy nie potrzeba
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1927,10 +1839,11 @@ bool TGround::Init(std::string File)
|
||||
RootEvent = tmp;
|
||||
if (!found)
|
||||
{ // jeśli nazwa wystąpiła, to do kolejki i wyszukiwarki dodawany jest tylko pierwszy
|
||||
if (RootEvent->Type != tp_Ignored)
|
||||
if (RootEvent->asName.find(
|
||||
"onstart") != std::string::npos) // event uruchamiany automatycznie po starcie
|
||||
AddToQuery(RootEvent, NULL); // dodanie do kolejki
|
||||
if( ( RootEvent->Type != tp_Ignored )
|
||||
&& ( RootEvent->asName.find( "onstart" ) != std::string::npos ) ) {
|
||||
// event uruchamiany automatycznie po starcie
|
||||
AddToQuery( RootEvent, NULL ); // dodanie do kolejki
|
||||
}
|
||||
m_eventmap.emplace( tmp->asName, tmp ); // dodanie do wyszukiwarki
|
||||
}
|
||||
}
|
||||
|
||||
47
Ground.h
47
Ground.h
@@ -21,8 +21,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Names.h"
|
||||
#include "lightarray.h"
|
||||
|
||||
using namespace Math3D;
|
||||
|
||||
typedef int TGroundNodeType;
|
||||
// Ra: zmniejszone liczby, aby zrobić tabelkę i zoptymalizować wyszukiwanie
|
||||
const int TP_MODEL = 10;
|
||||
@@ -95,8 +93,14 @@ struct TGroundVertex
|
||||
texture = interpolate( v1.texture, v2.texture, static_cast<float>( factor ) );
|
||||
}
|
||||
};
|
||||
|
||||
class TGroundNode : public Resource
|
||||
/*
|
||||
// ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node
|
||||
struct mesh_node {
|
||||
std::vector<TGroundVertex> vertices;
|
||||
geometry_handle geometry; // geometry prepared for drawing
|
||||
};
|
||||
*/
|
||||
class TGroundNode /*: public Resource*/
|
||||
{ // obiekt scenerii
|
||||
|
||||
friend class opengl_renderer;
|
||||
@@ -138,6 +142,9 @@ public:
|
||||
int iVersion; // wersja siatki (do wykonania rekompilacji)
|
||||
GLuint DisplayListID; // numer siatki DisplayLists
|
||||
int iVboPtr; // indeks w buforze VBO
|
||||
// NOTE: geometry handle is duplicated in (anim)model(3d), as well as in track and traction type nodes
|
||||
// TODO: clean this up when node types are refactored into an inheritance/composition scheme
|
||||
geometry_handle m_geometry; // geometry of the submodel
|
||||
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
|
||||
texture_handle TextureID; // główna (jedna) tekstura obiektu
|
||||
glm::vec3
|
||||
@@ -153,25 +160,10 @@ public:
|
||||
~TGroundNode();
|
||||
void Init(int n);
|
||||
void InitNormals();
|
||||
|
||||
// bool Disable();
|
||||
inline TGroundNode * Find(const std::string &asNameToFind, TGroundNodeType iNodeType)
|
||||
{ // wyszukiwanie czołgowe z typem
|
||||
if ((iNodeType == iType) && (asNameToFind == asName))
|
||||
return this;
|
||||
else if (nNext)
|
||||
return nNext->Find(asNameToFind, iNodeType);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
void Compile(glm::dvec3 const &Origin, bool const Multiple = false);
|
||||
/*
|
||||
void Release();
|
||||
|
||||
*/
|
||||
void RenderHidden(); // obsługa dźwięków i wyzwalaczy zdarzeń
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
// (McZapkie-131202)
|
||||
void RaRenderVBO(); // renderowanie (nieprzezroczystych) ze wspólnego VBO
|
||||
#endif
|
||||
};
|
||||
|
||||
struct bounding_area {
|
||||
@@ -180,7 +172,7 @@ struct bounding_area {
|
||||
float radius { 0.0f }; // radius of the bounding sphere
|
||||
};
|
||||
|
||||
class TSubRect : public Resource, public CMesh
|
||||
class TSubRect : /*public Resource,*/ public CMesh
|
||||
{ // sektor składowy kwadratu kilometrowego
|
||||
public:
|
||||
bounding_area m_area;
|
||||
@@ -209,12 +201,13 @@ class TSubRect : public Resource, public CMesh
|
||||
void LoadNodes(); // utworzenie VBO sektora
|
||||
public:
|
||||
virtual ~TSubRect();
|
||||
/*
|
||||
virtual void Release(); // zwalnianie VBO sektora
|
||||
*/
|
||||
void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
||||
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
|
||||
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
|
||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
|
||||
bool StartVBO(); // ustwienie VBO sektora dla (nRenderRect), (nRenderRectAlpha) i (nRenderWires)
|
||||
bool RaTrackAnimAdd(TTrack *t); // zgłoszenie toru do animacji
|
||||
void RaAnimate(); // przeliczenie animacji torów
|
||||
void RenderSounds(); // dźwięki pojazdów z niewidocznych sektorów
|
||||
@@ -244,7 +237,7 @@ private:
|
||||
public:
|
||||
virtual ~TGroundRect();
|
||||
// pobranie wskaźnika do małego kwadratu, utworzenie jeśli trzeba
|
||||
TSubRect * SafeGetRect(int iCol, int iRow) {
|
||||
TSubRect * SafeGetSubRect(int iCol, int iRow) {
|
||||
if( !pSubRects ) {
|
||||
// utworzenie małych kwadratów
|
||||
Init();
|
||||
@@ -252,7 +245,7 @@ public:
|
||||
return pSubRects + iRow * iNumSubRects + iCol; // zwrócenie właściwego
|
||||
};
|
||||
// pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
|
||||
TSubRect * FastGetRect(int iCol, int iRow) {
|
||||
TSubRect * FastGetSubRect(int iCol, int iRow) {
|
||||
return (pSubRects ? pSubRects + iRow * iNumSubRects + iCol : NULL);
|
||||
};
|
||||
// optymalizacja obiektów w sektorach
|
||||
@@ -282,7 +275,9 @@ class TGround
|
||||
*tmpEvent = nullptr,
|
||||
*tmp2Event = nullptr,
|
||||
*OldQRE = nullptr;
|
||||
/*
|
||||
TSubRect *pRendered[1500]; // lista renderowanych sektorów
|
||||
*/
|
||||
int iNumNodes = 0;
|
||||
vector3 pOrigin;
|
||||
vector3 aRotate;
|
||||
@@ -293,6 +288,7 @@ class TGround
|
||||
event_map m_eventmap;
|
||||
TNames<TGroundNode *> m_trackmap;
|
||||
light_array m_lights; // collection of dynamic light sources present in the scene
|
||||
bool PROBLEND;
|
||||
|
||||
private: // metody prywatne
|
||||
bool EventConditon(TEvent *e);
|
||||
@@ -351,7 +347,6 @@ class TGround
|
||||
private:
|
||||
void RaTriangleDivider(TGroundNode *node);
|
||||
void Navigate(std::string const &ClassName, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
bool PROBLEND;
|
||||
|
||||
public:
|
||||
void WyslijEvent(const std::string &e, const std::string &d);
|
||||
|
||||
43
Model3d.cpp
43
Model3d.cpp
@@ -1041,7 +1041,7 @@ void TSubModel::RaAnimation(TAnimType a)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void TSubModel::RaArrayFill(CVertNormTex *Vert)
|
||||
void TSubModel::RaArrayFill(basic_vertex *Vert)
|
||||
{ // wypełnianie tablic VBO
|
||||
if (Child)
|
||||
Child->RaArrayFill(Vert);
|
||||
@@ -1159,17 +1159,11 @@ TModel3d::~TModel3d()
|
||||
{
|
||||
// SafeDeleteArray(Materials);
|
||||
if (iFlags & 0x0200)
|
||||
{ // wczytany z pliku tekstowego, submodele sprzątają
|
||||
// same
|
||||
{ // wczytany z pliku tekstowego, submodele sprzątają same
|
||||
SafeDelete(Root); // submodele się usuną rekurencyjnie
|
||||
}
|
||||
else
|
||||
{ // wczytano z pliku binarnego (jest właścicielem tablic)
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
m_pVNT = nullptr; // nie usuwać tego, bo wskazuje na iModel
|
||||
#else
|
||||
m_pVNT.clear();
|
||||
#endif
|
||||
Root = nullptr;
|
||||
delete[] iModel; // usuwamy cały wczytany plik i to wystarczy
|
||||
}
|
||||
@@ -1344,6 +1338,9 @@ void TSubModel::serialize(std::ostream &s,
|
||||
|
||||
void TModel3d::SaveToBinFile(char const *FileName)
|
||||
{
|
||||
// TODO: re-implement!
|
||||
return;
|
||||
|
||||
WriteLog("saving e3d model..");
|
||||
|
||||
//m7todo: można by zoptymalizować robiąc unordered_map
|
||||
@@ -1379,18 +1376,20 @@ void TModel3d::SaveToBinFile(char const *FileName)
|
||||
sn_utils::ls_uint32(s, 8 + (uint32_t)transforms.size() * 64);
|
||||
for (size_t i = 0; i < transforms.size(); i++)
|
||||
transforms[i].serialize_float32(s);
|
||||
|
||||
/*
|
||||
MakeArray(iNumVerts);
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
Root->RaArrayFill(m_pVNT);
|
||||
#else
|
||||
Root->RaArrayFill( m_pVNT.data() );
|
||||
#endif
|
||||
*/
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('V', 'N', 'T', '0'));
|
||||
sn_utils::ls_uint32(s, 8 + iNumVerts * 32);
|
||||
/*
|
||||
for (size_t i = 0; i < (size_t)iNumVerts; i++)
|
||||
m_pVNT[i].serialize(s);
|
||||
|
||||
*/
|
||||
if (textures.size())
|
||||
{
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('T', 'E', 'X', '0'));
|
||||
@@ -1470,11 +1469,6 @@ void TSubModel::deserialize(std::istream &s)
|
||||
|
||||
void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
{
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
m_pVNT = nullptr;
|
||||
#else
|
||||
m_pVNT.clear();
|
||||
#endif
|
||||
Root = nullptr;
|
||||
float4x4 *tm = nullptr;
|
||||
if( m_geometrybank == NULL ) {
|
||||
@@ -1507,19 +1501,16 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
}
|
||||
else if (type == MAKE_ID4('V', 'N', 'T', '0'))
|
||||
{
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
if (m_pVNT != nullptr)
|
||||
#else
|
||||
if( false == m_pVNT.empty() )
|
||||
#endif
|
||||
throw std::runtime_error("e3d: duplicated VNT chunk");
|
||||
/*
|
||||
size_t vt_cnt = size / 32;
|
||||
if (m_pVNT != nullptr)
|
||||
throw std::runtime_error("e3d: duplicated VNT chunk");
|
||||
|
||||
size_t vt_cnt = size / 32;
|
||||
iNumVerts = (int)vt_cnt;
|
||||
m_nVertexCount = (int)vt_cnt;
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
assert( m_pVNT == nullptr );
|
||||
m_pVNT = new CVertNormTex[vt_cnt];
|
||||
m_pVNT = new basic_vertex[vt_cnt];
|
||||
#else
|
||||
m_pVNT.resize( vt_cnt );
|
||||
#endif
|
||||
@@ -1613,13 +1604,9 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
*/
|
||||
for (size_t i = 0; (int)i < iSubModelsCount; ++i)
|
||||
{
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
Root[i].BinInit( Root, tm, &Textures, &Names, dynamic );
|
||||
#else
|
||||
Root[ i ].BinInit( Root, tm, (float8*)m_pVNT.data(), &Textures, &Names, dynamic );
|
||||
#endif
|
||||
|
||||
if (Root[i].ChildGet())
|
||||
if (Root[i].ChildGet())
|
||||
Root[i].ChildGet()->Parent = &Root[i];
|
||||
if (Root[i].NextGet())
|
||||
Root[i].NextGet()->Parent = Root[i].Parent;
|
||||
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
TSubModel * GetFromName(char const *search, bool i = true);
|
||||
inline float4x4 * GetMatrix() { return fMatrix; };
|
||||
inline void Hide() { iVisible = 0; };
|
||||
void RaArrayFill(CVertNormTex *Vert);
|
||||
void RaArrayFill(basic_vertex *Vert);
|
||||
int FlagsCheck();
|
||||
void WillBeAnimated()
|
||||
{
|
||||
|
||||
113
Segment.cpp
113
Segment.cpp
@@ -319,16 +319,15 @@ vector3 TSegment::FastGetPoint(double t)
|
||||
return (bCurve ? RaInterpolate(t) : ((1.0 - t) * Point1 + (t)*Point2));
|
||||
}
|
||||
|
||||
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)
|
||||
bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, const vector6 *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale, int iSkip, int iEnd, double fOffsetX, vector3 **p, bool bRender)
|
||||
{ // 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
|
||||
int vertexcount{ 0 };
|
||||
|
||||
if( !fTsBuffer )
|
||||
return vertexcount; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
||||
return false; // prowizoryczne zabezpieczenie przed wysypem - ustalić faktyczną przyczynę
|
||||
|
||||
vector3 pos1, pos2, dir, parallel1, parallel2, pt, norm;
|
||||
double s, step, fOffset, tv1, tv2, t, fEnd;
|
||||
@@ -378,11 +377,6 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
|
||||
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;
|
||||
@@ -390,25 +384,12 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
|
||||
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
|
||||
::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->position.x = pt.x;
|
||||
Output->position.y = pt.y;
|
||||
Output->position.z = pt.z;
|
||||
Output->normal.x = norm.x;
|
||||
Output->normal.y = norm.y;
|
||||
Output->normal.z = norm.z;
|
||||
Output->texture.s = (jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
|
||||
Output->texture.t = tv1;
|
||||
++Output;
|
||||
}
|
||||
++vertexcount;
|
||||
if( bRender ) {
|
||||
// skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
||||
Output.emplace_back(
|
||||
glm::vec3 { pt.x, pt.y, pt.z },
|
||||
glm::vec3 { norm.x, norm.y, norm.z },
|
||||
glm::vec2 { ( jmm1 * ShapePoints[ j ].z + m1 * ShapePoints[ j + iNumShapePoints ].z ) / Texturescale, tv1 } );
|
||||
}
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if( *p )
|
||||
@@ -423,25 +404,12 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
|
||||
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
|
||||
::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->position.x = pt.x;
|
||||
Output->position.y = pt.y;
|
||||
Output->position.z = pt.z;
|
||||
Output->normal.x = norm.x;
|
||||
Output->normal.y = norm.y;
|
||||
Output->normal.z = norm.z;
|
||||
Output->texture.s = (jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z) / Texturescale;
|
||||
Output->texture.t = tv2;
|
||||
++Output;
|
||||
}
|
||||
++vertexcount;
|
||||
if( bRender ) {
|
||||
// skrzyżowania podczas łączenia siatek mogą nie renderować poboczy, ale potrzebować punktów
|
||||
Output.emplace_back(
|
||||
glm::vec3 { pt.x, pt.y, pt.z },
|
||||
glm::vec3 { norm.x, norm.y, norm.z },
|
||||
glm::vec2 { ( jmm2 * ShapePoints[ j ].z + m2 * ShapePoints[ j + iNumShapePoints ].z ) / Texturescale, tv2 } );
|
||||
}
|
||||
if( p ) // jeśli jest wskaźnik do tablicy
|
||||
if( *p )
|
||||
@@ -461,61 +429,30 @@ int TSegment::RenderLoft( CVertNormTex* &Output, Math3D::vector3 const &Origin,
|
||||
pt -= Origin;
|
||||
norm = ShapePoints[ j ].n.x * parallel1;
|
||||
norm.y += ShapePoints[ j ].n.y;
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
::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->position.x = pt.x;
|
||||
Output->position.y = pt.y;
|
||||
Output->position.z = pt.z;
|
||||
Output->normal.x = norm.x;
|
||||
Output->normal.y = norm.y;
|
||||
Output->normal.z = norm.z;
|
||||
Output->texture.s = ShapePoints[ j ].z / Texturescale;
|
||||
Output->texture.t = tv1;
|
||||
++Output;
|
||||
}
|
||||
++vertexcount;
|
||||
|
||||
Output.emplace_back(
|
||||
glm::vec3 { pt.x, pt.y, pt.z },
|
||||
glm::vec3 { norm.x, norm.y, norm.z },
|
||||
glm::vec2 { ShapePoints[ j ].z / Texturescale, tv1 } );
|
||||
|
||||
pt = parallel2 * ShapePoints[ j ].x + pos2;
|
||||
pt.y += ShapePoints[ j ].y;
|
||||
pt -= Origin;
|
||||
norm = ShapePoints[ j ].n.x * parallel2;
|
||||
norm.y += ShapePoints[ j ].n.y;
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
::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->position.x = pt.x;
|
||||
Output->position.y = pt.y;
|
||||
Output->position.z = pt.z;
|
||||
Output->normal.x = norm.x;
|
||||
Output->normal.y = norm.y;
|
||||
Output->normal.z = norm.z;
|
||||
Output->texture.s = ShapePoints[ j ].z / Texturescale;
|
||||
Output->texture.t = tv2;
|
||||
++Output;
|
||||
}
|
||||
++vertexcount;
|
||||
|
||||
Output.emplace_back(
|
||||
glm::vec3 { pt.x, pt.y, pt.z },
|
||||
glm::vec3 { norm.x, norm.y, norm.z },
|
||||
glm::vec2 { ShapePoints[ j ].z / Texturescale, tv2 } );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( Output == nullptr ) {
|
||||
// immediate mode
|
||||
glEnd();
|
||||
}
|
||||
pos1 = pos2;
|
||||
parallel1 = parallel2;
|
||||
tv1 = tv2;
|
||||
}
|
||||
|
||||
return vertexcount;
|
||||
return true;
|
||||
};
|
||||
|
||||
void TSegment::Render()
|
||||
|
||||
70
Segment.h
70
Segment.h
@@ -9,8 +9,10 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef SegmentH
|
||||
#define SegmentH
|
||||
|
||||
/*
|
||||
#include "VBO.h"
|
||||
*/
|
||||
#include "openglgeometrybank.h"
|
||||
#include "dumb3d.h"
|
||||
#include "Classes.h"
|
||||
#include "usefull.h"
|
||||
@@ -74,51 +76,35 @@ class TSegment
|
||||
bool bCurve = false;
|
||||
TSegment(TTrack *owner);
|
||||
~TSegment();
|
||||
bool Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1 = 0,
|
||||
double fNewRoll2 = 0);
|
||||
bool Init(vector3 NewPoint1, vector3 NewPoint2, double fNewStep, double fNewRoll1 = 0, double fNewRoll2 = 0);
|
||||
bool Init(vector3 &NewPoint1, vector3 NewCPointOut, vector3 NewCPointIn, vector3 &NewPoint2,
|
||||
double fNewStep, double fNewRoll1 = 0, double fNewRoll2 = 0, bool bIsCurve = true);
|
||||
inline double ComputeLength(); // McZapkie-150503
|
||||
inline vector3 GetDirection1()
|
||||
{
|
||||
return bCurve ? CPointOut - Point1 : CPointOut;
|
||||
};
|
||||
inline vector3 GetDirection2()
|
||||
{
|
||||
return bCurve ? CPointIn - Point2 : CPointIn;
|
||||
};
|
||||
inline vector3 GetDirection1() {
|
||||
return bCurve ? CPointOut - Point1 : CPointOut; };
|
||||
inline vector3 GetDirection2() {
|
||||
return bCurve ? CPointIn - Point2 : CPointIn; };
|
||||
vector3 GetDirection(double fDistance);
|
||||
vector3 GetDirection()
|
||||
{
|
||||
return CPointOut;
|
||||
};
|
||||
vector3 GetDirection() {
|
||||
return CPointOut; };
|
||||
vector3 FastGetDirection(double fDistance, double fOffset);
|
||||
vector3 GetPoint(double fDistance);
|
||||
void RaPositionGet(double fDistance, vector3 &p, vector3 &a);
|
||||
vector3 FastGetPoint(double t);
|
||||
inline vector3 FastGetPoint_0()
|
||||
{
|
||||
return Point1;
|
||||
};
|
||||
inline vector3 FastGetPoint_1()
|
||||
{
|
||||
return Point2;
|
||||
};
|
||||
inline double GetRoll(double const Distance)
|
||||
{
|
||||
return interpolate( fRoll1, fRoll2, Distance / fLength );
|
||||
}
|
||||
void GetRolls(double &r1, double &r2)
|
||||
{ // pobranie przechyłek (do generowania trójkątów)
|
||||
inline vector3 FastGetPoint_0() {
|
||||
return Point1; };
|
||||
inline vector3 FastGetPoint_1() {
|
||||
return Point2; };
|
||||
inline double GetRoll(double const Distance) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
r2 = fRoll2; }
|
||||
bool RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin, vector6 const *ShapePoints, int iNumShapePoints, double fTextureLength, double Texturescale = 1.0, int iSkip = 0, int iEnd = 0, double fOffsetX = 0.0, vector3 **p = nullptr, bool bRender = true);
|
||||
void Render();
|
||||
inline double GetLength()
|
||||
{
|
||||
return fLength;
|
||||
};
|
||||
inline double GetLength() {
|
||||
return fLength; };
|
||||
void MoveMe(vector3 pPosition)
|
||||
{
|
||||
Point1 += pPosition;
|
||||
@@ -129,14 +115,10 @@ class TSegment
|
||||
CPointOut += pPosition;
|
||||
}
|
||||
}
|
||||
int RaSegCount()
|
||||
{
|
||||
return fTsBuffer ? iSegCount : 1;
|
||||
};
|
||||
void AngleSet(int i, double a)
|
||||
{
|
||||
fAngle[i] = a;
|
||||
};
|
||||
int RaSegCount() {
|
||||
return fTsBuffer ? iSegCount : 1; };
|
||||
void AngleSet(int i, double a) {
|
||||
fAngle[i] = a; };
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
558
Track.cpp
558
Track.cpp
@@ -177,7 +177,6 @@ void TTrack::Init()
|
||||
case tt_Cross: // tylko dla skrzyżowania dróg
|
||||
SwitchExtension = std::make_shared<TSwitchExtension>( this, 6 ); // 6 po³¹czeñ
|
||||
SwitchExtension->vPoints = nullptr; // brak tablicy punktów
|
||||
SwitchExtension->iPoints = 0;
|
||||
SwitchExtension->bPoints = false; // tablica punktów nie wypełniona
|
||||
SwitchExtension->iRoads = 4; // domyślnie 4
|
||||
break;
|
||||
@@ -203,7 +202,9 @@ TTrack * TTrack::Create400m(int what, double dx)
|
||||
TSubRect *r = Global::pGround->GetSubRect(tmp->pCenter.x, tmp->pCenter.z);
|
||||
r->NodeAdd(tmp); // dodanie toru do segmentu
|
||||
r->Sort(); //żeby wyświetlał tabor z dodanego toru
|
||||
/*
|
||||
r->Release(); // usunięcie skompilowanych zasobów
|
||||
*/
|
||||
return trk;
|
||||
};
|
||||
|
||||
@@ -313,7 +314,9 @@ TTrack * TTrack::NullCreate(int dir)
|
||||
if (tmp2)
|
||||
r->NodeAdd(tmp2); // drugiego też
|
||||
r->Sort(); //żeby wyświetlał tabor z dodanego toru
|
||||
/*
|
||||
r->Release(); // usunięcie skompilowanych zasobów
|
||||
*/
|
||||
return trk;
|
||||
};
|
||||
|
||||
@@ -989,22 +992,6 @@ bool TTrack::AddDynamicObject(TDynamicObject *Dynamic)
|
||||
return true;
|
||||
};
|
||||
|
||||
void TTrack::MoveMe(vector3 pPosition)
|
||||
{ // to nie jest używane
|
||||
if (SwitchExtension)
|
||||
{
|
||||
SwitchExtension->Segments[0]->MoveMe(1 * pPosition);
|
||||
SwitchExtension->Segments[1]->MoveMe(1 * pPosition);
|
||||
SwitchExtension->Segments[2]->MoveMe(3 * pPosition); // Ra: 3 razy?
|
||||
SwitchExtension->Segments[3]->MoveMe(4 * pPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
Segment->MoveMe(pPosition);
|
||||
};
|
||||
ResourceManager::Unregister(this);
|
||||
};
|
||||
|
||||
const int numPts = 4;
|
||||
const int nnumPts = 12;
|
||||
|
||||
@@ -1039,10 +1026,10 @@ const vector6 iglica[nnumPts] = // iglica - vextor3(x,y,mapowanie tekstury)
|
||||
vector6(-0.040, -0.180, 1.00, -1.000, 0.000,
|
||||
0.000) // 1mm więcej, żeby nie nachodziły tekstury?
|
||||
};
|
||||
|
||||
/*
|
||||
void TTrack::Compile(GLuint tex)
|
||||
{
|
||||
CVertNormTex *immediate{ nullptr };
|
||||
basic_vertex *immediate{ nullptr };
|
||||
|
||||
// generowanie treści dla Display Lists - model proceduralny
|
||||
if (!tex)
|
||||
@@ -1656,14 +1643,16 @@ void TTrack::Compile(GLuint tex)
|
||||
if (Global::bManageNodes)
|
||||
glEndList();
|
||||
};
|
||||
|
||||
*/
|
||||
void TTrack::Release()
|
||||
{
|
||||
/*
|
||||
if (DisplayListID)
|
||||
glDeleteLists(DisplayListID, 1);
|
||||
DisplayListID = 0;
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
void TTrack::Render()
|
||||
{
|
||||
if (bVisible) // Ra: tory są renderowane sektorami i nie ma sensu każdorazowo liczyć odległości
|
||||
@@ -1682,7 +1671,7 @@ void TTrack::Render()
|
||||
Release(); // zwrotnica w trakcie animacji do odrysowania
|
||||
}
|
||||
};
|
||||
|
||||
*/
|
||||
bool TTrack::CheckDynamicObject(TDynamicObject *Dynamic)
|
||||
{ // sprawdzenie, czy pojazd jest przypisany do toru
|
||||
for( auto dynamic : Dynamics ) {
|
||||
@@ -1774,7 +1763,7 @@ void TTrack::RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joi
|
||||
am->GetContainer(NULL)->EventAssign(done); // zdarzenie zakończenia animacji
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
int TTrack::RaArrayPrepare()
|
||||
{ // przygotowanie tablic do skopiowania do VBO (zliczanie wierzchołków)
|
||||
if (bVisible) // o ile w ogóle widać
|
||||
@@ -1803,16 +1792,6 @@ int TTrack::RaArrayPrepare()
|
||||
+ SwitchExtension->Segments[ 4 ]->RaSegCount()
|
||||
+ SwitchExtension->Segments[ 5 ]->RaSegCount();
|
||||
}
|
||||
/*
|
||||
if (fTexHeight1 >= 0) {
|
||||
// normalne pobocze, na razie się składa z
|
||||
return ( ( TextureID1 ? SwitchExtension->iPoints + SwitchExtension->iRoads + 2 : 0 ) + ( TextureID2 ? SwitchExtension->iPoints * 12 : 0 ) );
|
||||
}
|
||||
else {
|
||||
// jeśli fTexHeight1<0, to są chodniki i może któregoś nie być
|
||||
return ( ( TextureID1 ? SwitchExtension->iPoints + SwitchExtension->iRoads + 2 : 0 ) + ( TextureID2 ? SwitchExtension->iPoints * 6 : 0 ) );
|
||||
}
|
||||
*/
|
||||
// each sub-segment covers only one side of the road, so it has points for single sideroad, if any
|
||||
return ( ( TextureID1 ? SwitchExtension->iPoints + SwitchExtension->iRoads + 2 : 0 ) + ( TextureID2 ? SwitchExtension->iPoints * 6 : 0 ) );
|
||||
}
|
||||
@@ -1829,28 +1808,28 @@ int TTrack::RaArrayPrepare()
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int const Vertexcount)
|
||||
{ // wypełnianie tablic VBO
|
||||
*/
|
||||
// wypełnianie tablic VBO
|
||||
void TTrack::create_geometry( geometrybank_handle const &Bank ) {
|
||||
// Ra: trzeba rozdzielić szyny od podsypki, aby móc grupować wg tekstur
|
||||
double fHTW = 0.5 * fabs(fTrackWidth);
|
||||
double side = fabs(fTexWidth); // szerokść podsypki na zewnątrz szyny albo pobocza
|
||||
double slop = fabs(fTexSlope); // brzeg zewnętrzny
|
||||
double rozp = fHTW + side + slop; // brzeg zewnętrzny
|
||||
double hypot1 = hypot(slop, fTexHeight1); // rozmiar pochylenia do liczenia normalnych
|
||||
double const fHTW = 0.5 * std::fabs(fTrackWidth);
|
||||
double const side = std::fabs(fTexWidth); // szerokść podsypki na zewnątrz szyny albo pobocza
|
||||
double const slop = std::fabs(fTexSlope); // brzeg zewnętrzny
|
||||
double const rozp = fHTW + side + slop; // brzeg zewnętrzny
|
||||
double hypot1 = std::hypot(slop, fTexHeight1); // rozmiar pochylenia do liczenia normalnych
|
||||
if (hypot1 == 0.0)
|
||||
hypot1 = 1.0;
|
||||
vector3 normal1 = vector3(fTexSlope / hypot1, fTexHeight1 / hypot1, 0.0); // wektor normalny
|
||||
vector3 normal1 { fTexSlope / hypot1, fTexHeight1 / hypot1, 0.0 }; // wektor normalny
|
||||
double fHTW2, side2, slop2, rozp2, fTexHeight2, hypot2;
|
||||
vector3 normal2;
|
||||
if (iTrapezoid & 2) // ten bit oznacza, że istnieje odpowiednie pNext
|
||||
{ // Ra: jest OK
|
||||
fHTW2 = 0.5 * fabs(trNext->fTrackWidth); // połowa rozstawu/nawierzchni
|
||||
side2 = fabs(trNext->fTexWidth);
|
||||
slop2 = fabs(trNext->fTexSlope); // nie jest używane później
|
||||
fHTW2 = 0.5 * std::fabs(trNext->fTrackWidth); // połowa rozstawu/nawierzchni
|
||||
side2 = std::fabs(trNext->fTexWidth);
|
||||
slop2 = std::fabs(trNext->fTexSlope); // nie jest używane później
|
||||
rozp2 = fHTW2 + side2 + slop2;
|
||||
fTexHeight2 = trNext->fTexHeight1;
|
||||
hypot2 = hypot(slop2, fTexHeight2);
|
||||
hypot2 = std::hypot(slop2, fTexHeight2);
|
||||
if (hypot2 == 0.0)
|
||||
hypot2 = 1.0;
|
||||
normal2 = vector3(trNext->fTexSlope / hypot2, fTexHeight2 / hypot2, 0.0);
|
||||
@@ -1877,37 +1856,48 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
Segment->GetRolls(roll1, roll2);
|
||||
else
|
||||
roll1 = roll2 = 0.0; // dla zwrotnic
|
||||
double sin1 = sin(roll1), cos1 = cos(roll1), sin2 = sin(roll2), cos2 = cos(roll2);
|
||||
double sin1 = std::sin(roll1), cos1 = std::cos(roll1), sin2 = std::sin(roll2), cos2 = std::cos(roll2);
|
||||
// zwykla szyna: //Ra: czemu główki są asymetryczne na wysokości 0.140?
|
||||
vector6 rpts1[24], rpts2[24], rpts3[24], rpts4[24];
|
||||
int i;
|
||||
for (i = 0; i < 12; ++i)
|
||||
{
|
||||
rpts1[i] = vector6((fHTW + szyna[i].x) * cos1 + szyna[i].y * sin1,
|
||||
-(fHTW + szyna[i].x) * sin1 + szyna[i].y * cos1, szyna[i].z,
|
||||
+szyna[i].n.x * cos1 + szyna[i].n.y * sin1,
|
||||
-szyna[i].n.x * sin1 + szyna[i].n.y * cos1, 0.0);
|
||||
rpts2[11 - i] = vector6((-fHTW - szyna[i].x) * cos1 + szyna[i].y * sin1,
|
||||
-(-fHTW - szyna[i].x) * sin1 + szyna[i].y * cos1, szyna[i].z,
|
||||
-szyna[i].n.x * cos1 + szyna[i].n.y * sin1,
|
||||
+szyna[i].n.x * sin1 + szyna[i].n.y * cos1, 0.0);
|
||||
rpts1[i] = vector6(
|
||||
(fHTW + szyna[i].x) * cos1 + szyna[i].y * sin1,
|
||||
-(fHTW + szyna[i].x) * sin1 + szyna[i].y * cos1,
|
||||
szyna[i].z,
|
||||
szyna[i].n.x * cos1 + szyna[i].n.y * sin1,
|
||||
-szyna[i].n.x * sin1 + szyna[i].n.y * cos1,
|
||||
0.0);
|
||||
rpts2[11 - i] = vector6(
|
||||
(-fHTW - szyna[i].x) * cos1 + szyna[i].y * sin1,
|
||||
-(-fHTW - szyna[i].x) * sin1 + szyna[i].y * cos1,
|
||||
szyna[i].z,
|
||||
-szyna[i].n.x * cos1 + szyna[i].n.y * sin1,
|
||||
szyna[i].n.x * sin1 + szyna[i].n.y * cos1,
|
||||
0.0);
|
||||
}
|
||||
if (iTrapezoid) // trapez albo przechyłki, to oddzielne punkty na końcu
|
||||
for (i = 0; i < 12; ++i)
|
||||
{
|
||||
rpts1[12 + i] = vector6((fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(fHTW2 + szyna[i].x) * sin2 + szyna[i].y * cos2,
|
||||
szyna[i].z, +szyna[i].n.x * cos2 + szyna[i].n.y * sin2,
|
||||
-szyna[i].n.x * sin2 + szyna[i].n.y * cos2, 0.0);
|
||||
rpts2[23 - i] = vector6((-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + szyna[i].y * cos2,
|
||||
szyna[i].z, -szyna[i].n.x * cos2 + szyna[i].n.y * sin2,
|
||||
+szyna[i].n.x * sin2 + szyna[i].n.y * cos2, 0.0);
|
||||
rpts1[12 + i] = vector6(
|
||||
(fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(fHTW2 + szyna[i].x) * sin2 + szyna[i].y * cos2,
|
||||
szyna[i].z,
|
||||
szyna[i].n.x * cos2 + szyna[i].n.y * sin2,
|
||||
-szyna[i].n.x * sin2 + szyna[i].n.y * cos2,
|
||||
0.0);
|
||||
rpts2[23 - i] = vector6(
|
||||
(-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + szyna[i].y * cos2,
|
||||
szyna[i].z,
|
||||
-szyna[i].n.x * cos2 + szyna[i].n.y * sin2,
|
||||
szyna[i].n.x * sin2 + szyna[i].n.y * cos2,
|
||||
0.0);
|
||||
}
|
||||
switch (eType) // dalej zależnie od typu
|
||||
{
|
||||
case tt_Table: // obrotnica jak zwykły tor, tylko animacja dochodzi
|
||||
SwitchExtension->iLeftVBO = Vert - Start; // indeks toru obrotnicy
|
||||
case tt_Normal:
|
||||
if (TextureID2)
|
||||
{ // podsypka z podkładami jest tylko dla zwykłego toru
|
||||
@@ -1969,12 +1959,33 @@ 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, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength);
|
||||
vertex_array vertices;
|
||||
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -4 : 4, fTexLength);
|
||||
if( ( Bank == 0 ) && ( false == Geometry2.empty() ) ) {
|
||||
// special variant, replace existing data for a turntable track
|
||||
GfxRenderer.Replace( vertices, Geometry2[ 0 ] );
|
||||
}
|
||||
else {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
}
|
||||
}
|
||||
if (TextureID1)
|
||||
{ // szyny - generujemy dwie, najwyżej rysować się będzie jedną
|
||||
Segment->RenderLoft(Vert, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
|
||||
Segment->RenderLoft(Vert, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength);
|
||||
vertex_array vertices;
|
||||
if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) {
|
||||
Segment->RenderLoft( vertices, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||
GfxRenderer.Replace( vertices, Geometry1[ 0 ] );
|
||||
vertices.clear(); // reuse the scratchpad
|
||||
Segment->RenderLoft( vertices, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||
GfxRenderer.Replace( vertices, Geometry1[ 1 ] );
|
||||
}
|
||||
else {
|
||||
Segment->RenderLoft( vertices, origin, rpts1, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear(); // reuse the scratchpad
|
||||
Segment->RenderLoft( vertices, origin, rpts2, iTrapezoid ? -nnumPts : nnumPts, fTexLength );
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case tt_Switch: // dla zwrotnicy dwa razy szyny
|
||||
@@ -1984,47 +1995,85 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
for (i = 0; i < 12; ++i)
|
||||
{
|
||||
rpts3[i] =
|
||||
vector6(+(fHTW + iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(+fHTW + iglica[i].x) * sin1 + iglica[i].y * cos1, iglica[i].z);
|
||||
vector6(
|
||||
+( fHTW + iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(+fHTW + iglica[i].x) * sin1 + iglica[i].y * cos1,
|
||||
iglica[i].z);
|
||||
rpts3[i + 12] =
|
||||
vector6(+(fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(+fHTW2 + szyna[i].x) * sin2 + iglica[i].y * cos2, szyna[i].z);
|
||||
vector6(
|
||||
+( fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(+fHTW2 + szyna[i].x) * sin2 + iglica[i].y * cos2,
|
||||
szyna[i].z);
|
||||
rpts4[11 - i] =
|
||||
vector6((-fHTW - iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(-fHTW - iglica[i].x) * sin1 + iglica[i].y * cos1, iglica[i].z);
|
||||
vector6(
|
||||
(-fHTW - iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(-fHTW - iglica[i].x) * sin1 + iglica[i].y * cos1,
|
||||
iglica[i].z);
|
||||
rpts4[23 - i] =
|
||||
vector6((-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + iglica[i].y * cos2, szyna[i].z);
|
||||
vector6(
|
||||
(-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + iglica[i].y * cos2,
|
||||
szyna[i].z);
|
||||
}
|
||||
// TODO, TBD: change all track geometry to triangles, to allow packing data in less, larger buffers
|
||||
if (SwitchExtension->RightSwitch)
|
||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||
vertex_array vertices;
|
||||
if( TextureID1 ) {
|
||||
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, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
||||
// fixed parts
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength );
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength, 1.0, 2 );
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
// left blade
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
if( TextureID2 ) {
|
||||
SwitchExtension->iRightVBO = Vert - Start; // indeks prawej iglicy
|
||||
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 );
|
||||
// fixed parts
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength );
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength, 1.0, 2 );
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
// right blade
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // lewa działa lepiej niż prawa
|
||||
vertex_array vertices;
|
||||
if( TextureID1 ) {
|
||||
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, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 ); // prawa iglica
|
||||
// fixed parts
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength, 1.0, 2 ); // prawa szyna za iglicą
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
// right blade
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
if( TextureID2 ) {
|
||||
SwitchExtension->iRightVBO = Vert - Start; // indeks prawej iglicy
|
||||
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
|
||||
// fixed parts
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength, 1.0, 2 ); // lewa szyna za iglicą
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
// left blade
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2059,7 +2108,9 @@ 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, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
||||
vertex_array vertices;
|
||||
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
}
|
||||
if (TextureID2)
|
||||
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
|
||||
@@ -2136,22 +2187,31 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
rpts2[5] = vector6(bpts1[3].x - side2, bpts1[3].y + h2l, 0.484375 - map2l); // lewy brzeg lewego chodnika
|
||||
}
|
||||
}
|
||||
vertex_array vertices;
|
||||
if( iTrapezoid ) // trapez albo przechyłki
|
||||
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony
|
||||
// odcinka
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
||||
Segment->RenderLoft( Vert, origin, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej
|
||||
Segment->RenderLoft( vertices, origin, rpts1, -3, fTexLength ); // tylko jeśli jest z prawej
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||
Segment->RenderLoft( Vert, origin, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej
|
||||
Segment->RenderLoft( vertices, origin, rpts2, -3, fTexLength ); // tylko jeśli jest z lewej
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
else { // pobocza zwykłe, brak przechyłki
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( slop != 0.0 ) ) {
|
||||
Segment->RenderLoft( Vert, origin, rpts1, 3, fTexLength );
|
||||
Segment->RenderLoft( vertices, origin, rpts1, 3, fTexLength );
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
if( ( fTexHeight1 >= 0.0 ) || ( side != 0.0 ) ) {
|
||||
Segment->RenderLoft( Vert, origin, rpts2, 3, fTexLength );
|
||||
Segment->RenderLoft( vertices, origin, rpts2, 3, fTexLength );
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2182,12 +2242,25 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
p[3] = SwitchExtension->Segments[1]->FastGetPoint_0(); // Point4 - przy trzech drogach pokrywa się z Point1
|
||||
// 2014-07: na początek rysować brzegi jak dla łuków
|
||||
// punkty brzegu nawierzchni uzyskujemy podczas renderowania boków (bez sensu, ale najszybciej było zrobić)
|
||||
int i; // ile punktów (może byc różna ilość punktów między drogami)
|
||||
int pointcount;
|
||||
if( SwitchExtension->iRoads == 3 ) {
|
||||
// mogą być tylko 3 drogi zamiast 4
|
||||
pointcount =
|
||||
SwitchExtension->Segments[ 0 ]->RaSegCount()
|
||||
+ SwitchExtension->Segments[ 1 ]->RaSegCount()
|
||||
+ SwitchExtension->Segments[ 2 ]->RaSegCount();
|
||||
}
|
||||
else {
|
||||
pointcount =
|
||||
SwitchExtension->Segments[ 2 ]->RaSegCount()
|
||||
+ SwitchExtension->Segments[ 3 ]->RaSegCount()
|
||||
+ SwitchExtension->Segments[ 4 ]->RaSegCount()
|
||||
+ SwitchExtension->Segments[ 5 ]->RaSegCount();
|
||||
}
|
||||
if (!SwitchExtension->vPoints)
|
||||
{ // jeśli tablica punktów nie jest jeszcze utworzona, zliczamy punkty i tworzymy ją
|
||||
// points were already counted during preparation stage
|
||||
// we'll need to add couple extra points for the complete fan we'll build
|
||||
SwitchExtension->vPoints = new vector3[SwitchExtension->iPoints + SwitchExtension->iRoads];
|
||||
SwitchExtension->vPoints = new vector3[pointcount + SwitchExtension->iRoads];
|
||||
}
|
||||
vector3 *b =
|
||||
SwitchExtension->bPoints ?
|
||||
@@ -2272,22 +2345,50 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
}
|
||||
}
|
||||
bool render = ( TextureID2 != 0 ); // renderować nie trzeba, ale trzeba wyznaczyć punkty brzegowe nawierzchni
|
||||
// if (iTrapezoid) //trapez albo przechyłki
|
||||
vertex_array vertices;
|
||||
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, 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 );
|
||||
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 3 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 4 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 5 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render );
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
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, 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
|
||||
SwitchExtension->Segments[ 2 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P2 do P4
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P4 do P3=P1 (odwrócony)
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, -3, fTexLength, 1.0, 0, 0, 0.0, &b, render ); // z P1 do P2
|
||||
if( true == render ) {
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2299,47 +2400,47 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
SwitchExtension->bPoints = true; // tablica punktów została wypełniona
|
||||
}
|
||||
|
||||
if (TextureID1) {
|
||||
if( TextureID1 ) {
|
||||
vertex_array vertices;
|
||||
// jeśli podana tekstura nawierzchni
|
||||
// we start with a vertex in the middle...
|
||||
Vert->normal.x = 0.0;
|
||||
Vert->normal.y = 1.0;
|
||||
Vert->normal.z = 0.0;
|
||||
Vert->texture.s = 0.5;
|
||||
Vert->texture.t = 0.5;
|
||||
Vert->position.x = oxz.x - origin.x;
|
||||
Vert->position.y = oxz.y - origin.y;
|
||||
Vert->position.z = oxz.z - origin.z;
|
||||
++Vert;
|
||||
vertices.emplace_back(
|
||||
glm::vec3{
|
||||
oxz.x - origin.x,
|
||||
oxz.y - origin.y,
|
||||
oxz.z - origin.z },
|
||||
glm::vec3{ 0.0f, 1.0f, 0.0f },
|
||||
glm::vec2{ 0.5f, 0.5f } );
|
||||
// ...and add one extra vertex to close the fan...
|
||||
Vert->normal.x = 0.0;
|
||||
Vert->normal.y = 1.0;
|
||||
Vert->normal.z = 0.0;
|
||||
// mapowanie we współrzędnych scenerii
|
||||
u = ( SwitchExtension->vPoints[ 0 ].x - oxz.x + origin.x ) / fTexLength;
|
||||
v = ( SwitchExtension->vPoints[ 0 ].z - oxz.z + origin.z ) / ( fTexRatio1 * fTexLength );
|
||||
Vert->texture.s = cosa0 * u + sina0 * v + 0.5;
|
||||
Vert->texture.t = -sina0 * u + cosa0 * v + 0.5;
|
||||
Vert->position.x = SwitchExtension->vPoints[ 0 ].x;
|
||||
Vert->position.y = SwitchExtension->vPoints[ 0 ].y;
|
||||
Vert->position.z = SwitchExtension->vPoints[ 0 ].z;
|
||||
++Vert;
|
||||
// ...then draw the precalculated rest
|
||||
for (i = SwitchExtension->iPoints + SwitchExtension->iRoads - 1; i >= 0; --i)
|
||||
{
|
||||
Vert->normal.x = 0.0;
|
||||
Vert->normal.y = 1.0;
|
||||
Vert->normal.z = 0.0;
|
||||
vertices.emplace_back(
|
||||
glm::vec3 {
|
||||
SwitchExtension->vPoints[ 0 ].x,
|
||||
SwitchExtension->vPoints[ 0 ].y,
|
||||
SwitchExtension->vPoints[ 0 ].z },
|
||||
glm::vec3{ 0.0f, 1.0f, 0.0f },
|
||||
// mapowanie we współrzędnych scenerii
|
||||
u = (SwitchExtension->vPoints[i].x - oxz.x + origin.x ) / fTexLength;
|
||||
v = (SwitchExtension->vPoints[i].z - oxz.z + origin.z ) / (fTexRatio1 * fTexLength);
|
||||
Vert->texture.s = cosa0 * u + sina0 * v + 0.5;
|
||||
Vert->texture.t = -sina0 * u + cosa0 * v + 0.5;
|
||||
Vert->position.x = SwitchExtension->vPoints[ i ].x;
|
||||
Vert->position.y = SwitchExtension->vPoints[ i ].y;
|
||||
Vert->position.z = SwitchExtension->vPoints[ i ].z;
|
||||
++Vert;
|
||||
glm::vec2{
|
||||
cosa0 * u + sina0 * v + 0.5,
|
||||
-sina0 * u + cosa0 * v + 0.5 } );
|
||||
// ...then draw the precalculated rest
|
||||
for (int i = pointcount + SwitchExtension->iRoads - 1; i >= 0; --i) {
|
||||
// mapowanie we współrzędnych scenerii
|
||||
u = ( SwitchExtension->vPoints[ i ].x - oxz.x + origin.x ) / fTexLength;
|
||||
v = ( SwitchExtension->vPoints[ i ].z - oxz.z + origin.z ) / ( fTexRatio1 * fTexLength );
|
||||
vertices.emplace_back(
|
||||
glm::vec3 {
|
||||
SwitchExtension->vPoints[ i ].x,
|
||||
SwitchExtension->vPoints[ i ].y,
|
||||
SwitchExtension->vPoints[ i ].z },
|
||||
glm::vec3{ 0.0f, 1.0f, 0.0f },
|
||||
// mapowanie we współrzędnych scenerii
|
||||
glm::vec2{
|
||||
cosa0 * u + sina0 * v + 0.5,
|
||||
-sina0 * u + cosa0 * v + 0.5 } );
|
||||
}
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_FAN ) );
|
||||
}
|
||||
break;
|
||||
} // tt_cross
|
||||
@@ -2378,11 +2479,13 @@ 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, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
||||
vertex_array vertices;
|
||||
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
|
||||
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
}
|
||||
if (TextureID2)
|
||||
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w
|
||||
// Midtown Madness 2?)
|
||||
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
|
||||
vertex_array vertices;
|
||||
vector6 rpts1[6],
|
||||
rpts2[6]; // współrzędne przekroju i mapowania dla prawej i lewej strony
|
||||
rpts1[0] = vector6(rozp, -fTexHeight1, 0.0); // lewy brzeg podstawy
|
||||
@@ -2400,13 +2503,21 @@ 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, origin, rpts1, -3, fTexLength);
|
||||
Segment->RenderLoft(Vert, origin, rpts2, -3, fTexLength);
|
||||
Segment->RenderLoft(vertices, origin, rpts1, -3, fTexLength);
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
Segment->RenderLoft(vertices, origin, rpts2, -3, fTexLength);
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
else
|
||||
{ // pobocza zwykłe, brak przechyłki
|
||||
Segment->RenderLoft(Vert, origin, rpts1, 3, fTexLength);
|
||||
Segment->RenderLoft(Vert, origin, rpts2, 3, fTexLength);
|
||||
Segment->RenderLoft(vertices, origin, rpts1, 3, fTexLength);
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
Segment->RenderLoft(vertices, origin, rpts2, 3, fTexLength);
|
||||
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2415,10 +2526,9 @@ void TTrack::RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int cons
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
/*
|
||||
void TTrack::RaRenderVBO( int iPtr ) { // renderowanie z użyciem VBO
|
||||
// Ra 2014-07: trzeba wymienić GL_TRIANGLE_STRIP na GL_TRIANGLES i renderować trójkąty sektora
|
||||
// dla kolejnych tekstur!
|
||||
// Ra 2014-07: trzeba wymienić GL_TRIANGLE_STRIP na GL_TRIANGLES i renderować trójkąty sektora dla kolejnych tekstur!
|
||||
EnvironmentSet();
|
||||
int seg;
|
||||
switch( iCategoryFlag & 15 ) {
|
||||
@@ -2568,7 +2678,7 @@ void TTrack::RaRenderVBO( int iPtr ) { // renderowanie z użyciem VBO
|
||||
}
|
||||
EnvironmentReset();
|
||||
};
|
||||
|
||||
*/
|
||||
void TTrack::EnvironmentSet()
|
||||
{ // ustawienie zmienionego światła
|
||||
glColor3f(1.0f, 1.0f, 1.0f); // Ra: potrzebne to?
|
||||
@@ -2822,11 +2932,11 @@ void TTrack::RaAnimListAdd(TTrack *t)
|
||||
}
|
||||
};
|
||||
|
||||
TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer)
|
||||
TTrack * TTrack::RaAnimate()
|
||||
{ // wykonanie rekurencyjne animacji, wywoływane przed wyświetleniem sektora
|
||||
// zwraca wskaźnik toru wymagającego dalszej animacji
|
||||
if( SwitchExtension->pNextAnim )
|
||||
SwitchExtension->pNextAnim = SwitchExtension->pNextAnim->RaAnimate( Vertexbuffer );
|
||||
SwitchExtension->pNextAnim = SwitchExtension->pNextAnim->RaAnimate();
|
||||
bool m = true; // animacja trwa
|
||||
if (eType == tt_Switch) // dla zwrotnicy tylko szyny
|
||||
{
|
||||
@@ -2855,77 +2965,85 @@ TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer)
|
||||
m = false; // koniec animacji
|
||||
}
|
||||
}
|
||||
if( ( Global::bUseVBO )
|
||||
&& ( Vertexbuffer != -1 ) )
|
||||
{ // dla OpenGL 1.4 odświeży się cały sektor, w późniejszych poprawiamy fragment
|
||||
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
|
||||
if (TextureID1) // Ra: !!!! tu jest do poprawienia
|
||||
{ // iglice liczone tylko dla zwrotnic
|
||||
vector6 rpts3[24], rpts4[24];
|
||||
double fHTW = 0.5 * fabs(fTrackWidth);
|
||||
double fHTW2 = fHTW; // Ra: na razie niech tak będzie
|
||||
double cos1 = 1.0, sin1 = 0.0, cos2 = 1.0, sin2 = 0.0; // Ra: ...
|
||||
for( int i = 0; i < 12; ++i ) {
|
||||
// skip the geometry update if no geometry for this track was generated yet
|
||||
if( ( ( TextureID1 != 0 )
|
||||
|| ( TextureID2 != 0 ) )
|
||||
&& ( ( false == Geometry1.empty() )
|
||||
|| ( false == Geometry2.empty() ) ) ) {
|
||||
// iglice liczone tylko dla zwrotnic
|
||||
double fHTW = 0.5 * fabs( fTrackWidth );
|
||||
double fHTW2 = fHTW; // Ra: na razie niech tak będzie
|
||||
double cos1 = 1.0, sin1 = 0.0, cos2 = 1.0, sin2 = 0.0; // Ra: ...
|
||||
vector6 rpts3[ 24 ], rpts4[ 24 ];
|
||||
for (int i = 0; i < 12; ++i)
|
||||
{
|
||||
rpts3[i] =
|
||||
vector6(
|
||||
+( fHTW + iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(+fHTW + iglica[i].x) * sin1 + iglica[i].y * cos1,
|
||||
iglica[i].z);
|
||||
rpts3[i + 12] =
|
||||
vector6(
|
||||
+( fHTW2 + szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(+fHTW2 + szyna[i].x) * sin2 + iglica[i].y * cos2,
|
||||
szyna[i].z);
|
||||
rpts4[11 - i] =
|
||||
vector6(
|
||||
(-fHTW - iglica[i].x) * cos1 + iglica[i].y * sin1,
|
||||
-(-fHTW - iglica[i].x) * sin1 + iglica[i].y * cos1,
|
||||
iglica[i].z);
|
||||
rpts4[23 - i] =
|
||||
vector6(
|
||||
(-fHTW2 - szyna[i].x) * cos2 + szyna[i].y * sin2,
|
||||
-(-fHTW2 - szyna[i].x) * sin2 + iglica[i].y * cos2,
|
||||
szyna[i].z);
|
||||
}
|
||||
|
||||
rpts3[ i ] =
|
||||
vector6( +( fHTW + iglica[ i ].x ) * cos1 + iglica[ i ].y * sin1,
|
||||
-( +fHTW + iglica[ i ].x ) * sin1 + iglica[ i ].y * cos1, iglica[ i ].z );
|
||||
rpts3[ i + 12 ] =
|
||||
vector6( +( fHTW2 + szyna[ i ].x ) * cos2 + szyna[ i ].y * sin2,
|
||||
-( +fHTW2 + szyna[ i ].x ) * sin2 + iglica[ i ].y * cos2, szyna[ i ].z );
|
||||
rpts4[ 11 - i ] =
|
||||
vector6( ( -fHTW - iglica[ i ].x ) * cos1 + iglica[ i ].y * sin1,
|
||||
-( -fHTW - iglica[ i ].x ) * sin1 + iglica[ i ].y * cos1, iglica[ i ].z );
|
||||
rpts4[ 23 - i ] =
|
||||
vector6( ( -fHTW2 - szyna[ i ].x ) * cos2 + szyna[ i ].y * sin2,
|
||||
-( -fHTW2 - szyna[ i ].x ) * sin2 + iglica[ i ].y * cos2, szyna[ i ].z );
|
||||
}
|
||||
// NOTE: performance-wise it'd make much more sense to keep the most recent shape cached as part of switch extension,
|
||||
// and only send updates when/if they take place, instead of the current back-and-forth
|
||||
// TODO: implement optimized version
|
||||
auto const origin { pMyNode->m_rootposition };
|
||||
vertex_array vertices;
|
||||
|
||||
// fetch current blade geometry
|
||||
std::vector<CVertNormTex> bladesbuffer; bladesbuffer.resize( 2 * 2 * 24 ); // 2 blades, 2 segments each
|
||||
/*
|
||||
::glGetBufferSubData(
|
||||
GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iLeftVBO * sizeof( CVertNormTex ),
|
||||
bladesbuffer.size() * sizeof( CVertNormTex ),
|
||||
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, 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, 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(
|
||||
GL_ARRAY_BUFFER,
|
||||
SwitchExtension->iLeftVBO * sizeof( CVertNormTex ),
|
||||
bladesbuffer.size() * sizeof( CVertNormTex ),
|
||||
bladesbuffer.data() );
|
||||
if (SwitchExtension->RightSwitch)
|
||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||
vertex_array vertices;
|
||||
if( TextureID1 ) {
|
||||
// left blade
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
||||
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
||||
vertices.clear();
|
||||
}
|
||||
if( TextureID2 ) {
|
||||
// right blade
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
|
||||
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
else { // lewa działa lepiej niż prawa
|
||||
vertex_array vertices;
|
||||
if( TextureID1 ) {
|
||||
// right blade
|
||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
||||
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
|
||||
vertices.clear();
|
||||
}
|
||||
if( TextureID2 ) {
|
||||
// left blade
|
||||
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
|
||||
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
|
||||
vertices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
else // gdy Display List
|
||||
Release(); // niszczenie skompilowanej listy, aby się wygenerowała nowa
|
||||
}
|
||||
else if (eType == tt_Table) // dla obrotnicy - szyny i podsypka
|
||||
{
|
||||
else if (eType == tt_Table) {
|
||||
// dla obrotnicy - szyny i podsypka
|
||||
if (SwitchExtension->pModel &&
|
||||
SwitchExtension->CurrentIndex) // 0=zablokowana się nie animuje
|
||||
{ // trzeba każdorazowo porównywać z kątem modelu
|
||||
// SwitchExtension->fOffset1=SwitchExtension->pAnim?SwitchExtension->pAnim->AngleGet():0.0;
|
||||
// //pobranie kąta z modelu
|
||||
TAnimContainer *ac = SwitchExtension->pModel ?
|
||||
SwitchExtension->pModel->GetContainer(NULL) :
|
||||
NULL; // pobranie głównego submodelu
|
||||
// if (ac) ac->EventAssign(SwitchExtension->evMinus); //event zakończenia animacji,
|
||||
// trochę bez sensu tutaj
|
||||
if (ac)
|
||||
if ((ac->AngleGet() != SwitchExtension->fOffset) ||
|
||||
!(ac->TransGet() ==
|
||||
@@ -2947,22 +3065,26 @@ TTrack * TTrack::RaAnimate(GLuint const Vertexbuffer)
|
||||
dynamic->Move( 0.000001 );
|
||||
}
|
||||
// kąty
|
||||
/*
|
||||
if (Global::bUseVBO)
|
||||
{ // dla OpenGL 1.4 odświeży się cały sektor, w późniejszych poprawiamy fragment
|
||||
// aktualizacja pojazdów na torze
|
||||
if (GLEW_VERSION_1_5) // dla OpenGL 1.4 to się nie wykona poprawnie
|
||||
{
|
||||
int size = RaArrayPrepare(); // wielkość tabeli potrzebna dla tej obrotnicy
|
||||
CVertNormTex *Vert = new CVertNormTex[size]; // bufor roboczy
|
||||
// CVertNormTex *v=Vert; //zmieniane przez
|
||||
basic_vertex *Vert = new basic_vertex[size]; // bufor roboczy
|
||||
// basic_vertex *v=Vert; //zmieniane przez
|
||||
RaArrayFill(Vert, Vert - SwitchExtension->iLeftVBO, size); // iLeftVBO powinno zostać niezmienione
|
||||
::glBufferSubData(
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(CVertNormTex),
|
||||
size * sizeof(CVertNormTex), Vert); // wysłanie fragmentu bufora VBO
|
||||
GL_ARRAY_BUFFER, SwitchExtension->iLeftVBO * sizeof(basic_vertex),
|
||||
size * sizeof(basic_vertex), Vert); // wysłanie fragmentu bufora VBO
|
||||
}
|
||||
}
|
||||
else // gdy Display List
|
||||
Release(); // niszczenie skompilowanej listy, aby się wygenerowała nowa
|
||||
*/
|
||||
// NOTE: passing empty handle is a bit of a hack here. could be refactored into something more elegant
|
||||
create_geometry( geometrybank_handle() );
|
||||
} // animacja trwa nadal
|
||||
}
|
||||
else
|
||||
|
||||
138
Track.h
138
Track.h
@@ -15,8 +15,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Segment.h"
|
||||
#include "Texture.h"
|
||||
|
||||
class TEvent;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
tt_Unknown,
|
||||
@@ -39,6 +37,7 @@ typedef enum
|
||||
} TEnvironmentType;
|
||||
// Ra: opracować alternatywny system cieni/świateł z definiowaniem koloru oświetlenia w halach
|
||||
|
||||
class TEvent;
|
||||
class TTrack;
|
||||
class TGroundNode;
|
||||
class TSubRect;
|
||||
@@ -77,10 +76,10 @@ class TSwitchExtension
|
||||
};
|
||||
struct
|
||||
{ // zmienne dla skrzyżowania
|
||||
vector3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze
|
||||
int iPoints; // liczba faktycznie użytych wierzchołków nawierzchni
|
||||
bool bPoints; // czy utworzone?
|
||||
int iRoads; // ile dróg się spotyka?
|
||||
vector3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze
|
||||
// int iPoints; // liczba faktycznie użytych wierzchołków nawierzchni
|
||||
bool bPoints; // czy utworzone?
|
||||
};
|
||||
};
|
||||
bool bMovement = false; // czy w trakcie animacji
|
||||
@@ -108,46 +107,48 @@ class TIsolated
|
||||
TIsolated();
|
||||
TIsolated(const std::string &n, TIsolated *i);
|
||||
~TIsolated();
|
||||
static TIsolated * Find(
|
||||
const std::string &n); // znalezienie obiektu albo utworzenie nowego
|
||||
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
|
||||
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
|
||||
bool Busy()
|
||||
{
|
||||
return (iAxles > 0);
|
||||
};
|
||||
static TIsolated * Root()
|
||||
{
|
||||
return (pRoot);
|
||||
};
|
||||
TIsolated * Next()
|
||||
{
|
||||
return (pNext);
|
||||
};
|
||||
bool Busy() {
|
||||
return (iAxles > 0); };
|
||||
static TIsolated * Root() {
|
||||
return (pRoot); };
|
||||
TIsolated * Next() {
|
||||
return (pNext); };
|
||||
};
|
||||
|
||||
class TTrack : public Resource
|
||||
{ // trajektoria ruchu - opakowanie
|
||||
private:
|
||||
// trajektoria ruchu - opakowanie
|
||||
class TTrack : public Resource {
|
||||
|
||||
friend class opengl_renderer;
|
||||
|
||||
private:
|
||||
TGroundNode * pMyNode = nullptr; // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
|
||||
TIsolated * pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
|
||||
std::shared_ptr<TSwitchExtension> SwitchExtension; // dodatkowe dane do toru, który jest zwrotnicą
|
||||
std::shared_ptr<TSegment> Segment;
|
||||
TTrack *trNext = nullptr; // odcinek od strony punktu 2 - to powinno być w segmencie
|
||||
TTrack *trPrev = nullptr; // odcinek od strony punktu 1
|
||||
TTrack * trNext = nullptr; // odcinek od strony punktu 2 - to powinno być w segmencie
|
||||
TTrack * trPrev = nullptr; // odcinek od strony punktu 1
|
||||
|
||||
// McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
|
||||
texture_handle TextureID1 = 0; // tekstura szyn albo nawierzchni
|
||||
texture_handle TextureID2 = 0; // tekstura automatycznej podsypki albo pobocza
|
||||
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
|
||||
double fRadiusTable[ 2 ]; // dwa promienie, drugi dla zwrotnicy
|
||||
float fTexLength = 4.0f; // długość powtarzania tekstury w metrach
|
||||
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
|
||||
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
|
||||
float fTexHeight1 = 0.6f; // wysokość brzegu względem trajektorii
|
||||
float fTexWidth = 0.9f; // szerokość boku
|
||||
float fTexSlope = 0.9f;
|
||||
double fRadiusTable[ 2 ]; // dwa promienie, drugi dla zwrotnicy
|
||||
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
|
||||
/*
|
||||
GLuint DisplayListID = 0;
|
||||
TIsolated *pIsolated = nullptr; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
|
||||
TGroundNode *
|
||||
pMyNode = nullptr; // Ra: proteza, żeby tor znał swoją nazwę TODO: odziedziczyć TTrack z TGroundNode
|
||||
public:
|
||||
*/
|
||||
texture_handle TextureID1 = 0; // tekstura szyn albo nawierzchni
|
||||
texture_handle TextureID2 = 0; // tekstura automatycznej podsypki albo pobocza
|
||||
typedef std::vector<geometry_handle> geometryhandle_sequence;
|
||||
geometryhandle_sequence Geometry1; // geometry chunks textured with texture 1
|
||||
geometryhandle_sequence Geometry2; // geometry chunks textured with texture 2
|
||||
|
||||
public:
|
||||
typedef std::deque<TDynamicObject *> dynamics_sequence;
|
||||
dynamics_sequence Dynamics;
|
||||
int iEvents = 0; // Ra: flaga informująca o obecności eventów
|
||||
@@ -193,39 +194,30 @@ class TTrack : public Resource
|
||||
void Init();
|
||||
static TTrack * Create400m(int what, double dx);
|
||||
TTrack * NullCreate(int dir);
|
||||
inline bool IsEmpty()
|
||||
{
|
||||
return Dynamics.empty();
|
||||
};
|
||||
inline bool IsEmpty() {
|
||||
return Dynamics.empty(); };
|
||||
void ConnectPrevPrev(TTrack *pNewPrev, int typ);
|
||||
void ConnectPrevNext(TTrack *pNewPrev, int typ);
|
||||
void ConnectNextPrev(TTrack *pNewNext, int typ);
|
||||
void ConnectNextNext(TTrack *pNewNext, int typ);
|
||||
inline double Length()
|
||||
{
|
||||
return Segment->GetLength();
|
||||
};
|
||||
inline std::shared_ptr<TSegment> CurrentSegment()
|
||||
{
|
||||
return Segment;
|
||||
};
|
||||
inline TTrack * CurrentNext()
|
||||
{
|
||||
return (trNext);
|
||||
};
|
||||
inline TTrack * CurrentPrev()
|
||||
{
|
||||
return (trPrev);
|
||||
};
|
||||
inline double Length() {
|
||||
return Segment->GetLength(); };
|
||||
inline std::shared_ptr<TSegment> CurrentSegment() {
|
||||
return Segment; };
|
||||
inline TTrack * CurrentNext() {
|
||||
return (trNext); };
|
||||
inline TTrack * CurrentPrev() {
|
||||
return (trPrev); };
|
||||
TTrack * Neightbour(int s, double &d);
|
||||
bool SetConnections(int i);
|
||||
bool Switch(int i, double t = -1.0, double d = -1.0);
|
||||
bool SwitchForced(int i, TDynamicObject *o);
|
||||
int CrossSegment(int from, int into);
|
||||
inline int GetSwitchState()
|
||||
{
|
||||
return (SwitchExtension ? SwitchExtension->CurrentIndex : -1);
|
||||
};
|
||||
inline int GetSwitchState() {
|
||||
return (
|
||||
SwitchExtension ?
|
||||
SwitchExtension->CurrentIndex :
|
||||
-1); };
|
||||
void Load(cParser *parser, vector3 pOrigin, std::string name);
|
||||
bool AssignEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
||||
bool AssignallEvents(TEvent *NewEvent0, TEvent *NewEvent1, TEvent *NewEvent2);
|
||||
@@ -233,44 +225,42 @@ class TTrack : public Resource
|
||||
bool CheckDynamicObject(TDynamicObject *Dynamic);
|
||||
bool AddDynamicObject(TDynamicObject *Dynamic);
|
||||
bool RemoveDynamicObject(TDynamicObject *Dynamic);
|
||||
void MoveMe(vector3 pPosition);
|
||||
|
||||
void Release();
|
||||
/*
|
||||
void Compile(GLuint tex = 0);
|
||||
|
||||
void Render(); // renderowanie z Display Lists
|
||||
int RaArrayPrepare(); // zliczanie rozmiaru dla VBO sektroa
|
||||
void RaArrayFill(CVertNormTex *Vert, const CVertNormTex *Start, int const Vertexcount); // wypełnianie VBO
|
||||
*/
|
||||
void create_geometry(geometrybank_handle const &Bank); // wypełnianie VBO
|
||||
/*
|
||||
void RaRenderVBO(int iPtr); // renderowanie z VBO sektora
|
||||
*/
|
||||
void RenderDyn(); // renderowanie nieprzezroczystych pojazdów (oba tryby)
|
||||
void RenderDynAlpha(); // renderowanie przezroczystych pojazdów (oba tryby)
|
||||
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich
|
||||
// wyświetlania
|
||||
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
|
||||
|
||||
void RaOwnerSet(TSubRect *o)
|
||||
{
|
||||
void RaOwnerSet(TSubRect *o) {
|
||||
if (SwitchExtension)
|
||||
SwitchExtension->pOwner = o;
|
||||
};
|
||||
SwitchExtension->pOwner = o; };
|
||||
bool InMovement(); // czy w trakcie animacji?
|
||||
void RaAssign(TGroundNode *gn, TAnimContainer *ac);
|
||||
void RaAssign(TGroundNode *gn, TAnimModel *am, TEvent *done, TEvent *joined);
|
||||
void RaAnimListAdd(TTrack *t);
|
||||
TTrack * RaAnimate(GLuint const Vertexbuffer = -1);
|
||||
TTrack * RaAnimate();
|
||||
|
||||
void RadioStop();
|
||||
void AxleCounter(int i, TDynamicObject *o)
|
||||
{
|
||||
void AxleCounter(int i, TDynamicObject *o) {
|
||||
if (pIsolated)
|
||||
pIsolated->Modify(i, o);
|
||||
}; // dodanie lub odjęcie osi
|
||||
pIsolated->Modify(i, o); }; // dodanie lub odjęcie osi
|
||||
std::string IsolatedName();
|
||||
bool IsolatedEventsAssign(TEvent *busy, TEvent *free);
|
||||
double WidthTotal();
|
||||
GLuint TextureGet(int i)
|
||||
{
|
||||
return i ? TextureID1 : TextureID2;
|
||||
};
|
||||
GLuint TextureGet(int i) {
|
||||
return (
|
||||
i ?
|
||||
TextureID1 :
|
||||
TextureID2 ); };
|
||||
bool IsGroupable();
|
||||
int TestPoint(vector3 *Point);
|
||||
void MovedUp1(double dh);
|
||||
|
||||
@@ -358,7 +358,7 @@ void TTraction::ResistanceCalc(int d, double r, TTractionPowerSource *ps)
|
||||
}
|
||||
t->psPower[d] = ps; // skopiowanie wskaźnika zasilacza od danej strony
|
||||
t->fResistance[d] = r; // wpisanie rezystancji w kierunku tego zasilacza
|
||||
r += t->fResistivity * glm::dot(t->vParametric, t->vParametric ); // doliczenie oporu kolejnego odcinka
|
||||
r += t->fResistivity * glm::length(t->vParametric); // doliczenie oporu kolejnego odcinka
|
||||
p = t; // zapamiętanie dotychczasowego
|
||||
t = p->hvNext[d ^ 1]; // podążanie w tę samą stronę
|
||||
d = p->iNext[d ^ 1];
|
||||
@@ -367,8 +367,7 @@ void TTraction::ResistanceCalc(int d, double r, TTractionPowerSource *ps)
|
||||
}
|
||||
else
|
||||
{ // podążanie w obu kierunkach, można by rekurencją, ale szkoda zasobów
|
||||
r = 0.5 * fResistivity *
|
||||
glm::dot(vParametric, vParametric ); // powiedzmy, że w zasilanym przęśle jest połowa
|
||||
r = 0.5 * fResistivity * glm::length(vParametric); // powiedzmy, że w zasilanym przęśle jest połowa
|
||||
if (fResistance[0] == 0.0)
|
||||
ResistanceCalc(0, r); // do tyłu (w stronę Point1)
|
||||
if (fResistance[1] == 0.0)
|
||||
|
||||
@@ -56,7 +56,7 @@ class TTraction
|
||||
void Connect(int my, TTraction *with, int to);
|
||||
void Init();
|
||||
bool WhereIs();
|
||||
void ResistanceCalc(int d = -1, double r = 0, TTractionPowerSource *ps = NULL);
|
||||
void ResistanceCalc(int d = -1, double r = 0, TTractionPowerSource *ps = nullptr);
|
||||
void PowerSet(TTractionPowerSource *ps);
|
||||
double VoltageGet(double u, double i);
|
||||
private:
|
||||
|
||||
145
VBO.cpp
145
VBO.cpp
@@ -9,148 +9,3 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "VBO.h"
|
||||
#include "GL/glew.h"
|
||||
#include "usefull.h"
|
||||
#include "sn_utils.h"
|
||||
#include "globals.h"
|
||||
//---------------------------------------------------------------------------
|
||||
/*
|
||||
void CVertNormTex::deserialize(std::istream &s)
|
||||
{
|
||||
x = sn_utils::ld_float32(s);
|
||||
y = sn_utils::ld_float32(s);
|
||||
z = sn_utils::ld_float32(s);
|
||||
|
||||
nx = sn_utils::ld_float32(s);
|
||||
ny = sn_utils::ld_float32(s);
|
||||
nz = sn_utils::ld_float32(s);
|
||||
|
||||
u = sn_utils::ld_float32(s);
|
||||
v = sn_utils::ld_float32(s);
|
||||
}
|
||||
|
||||
void CVertNormTex::serialize(std::ostream &s)
|
||||
{
|
||||
sn_utils::ls_float32(s, x);
|
||||
sn_utils::ls_float32(s, y);
|
||||
sn_utils::ls_float32(s, z);
|
||||
|
||||
sn_utils::ls_float32(s, nx);
|
||||
sn_utils::ls_float32(s, ny);
|
||||
sn_utils::ls_float32(s, nz);
|
||||
|
||||
sn_utils::ls_float32(s, u);
|
||||
sn_utils::ls_float32(s, v);
|
||||
}
|
||||
*/
|
||||
CMesh::CMesh()
|
||||
{ // utworzenie pustego obiektu
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
m_pVNT = nullptr;
|
||||
#endif
|
||||
m_nVertexCount = -1;
|
||||
m_nVBOVertices = 0; // nie zarezerwowane
|
||||
};
|
||||
|
||||
CMesh::~CMesh()
|
||||
{ // usuwanie obiektu
|
||||
Clear(); // zwolnienie zasobów
|
||||
};
|
||||
|
||||
void CMesh::MakeArray(int n)
|
||||
{ // tworzenie tablic
|
||||
m_nVertexCount = n;
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
assert( m_pVNT == nullptr );
|
||||
m_pVNT = new CVertNormTex[m_nVertexCount]; // przydzielenie pamięci dla tablicy
|
||||
#else
|
||||
m_pVNT.clear();
|
||||
m_pVNT.resize( m_nVertexCount );
|
||||
#endif
|
||||
};
|
||||
|
||||
void CMesh::BuildVBOs(bool del)
|
||||
{ // tworzenie VBO i kasowanie już niepotrzebnych tablic
|
||||
// pobierz numer VBO oraz ustaw go jako aktywny
|
||||
glGenBuffers(1, &m_nVBOVertices); // pobierz numer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_nVBOVertices); // ustaw bufor jako aktualny
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
glBufferData(GL_ARRAY_BUFFER, m_nVertexCount * sizeof(CVertNormTex), m_pVNT, GL_STATIC_DRAW);
|
||||
#else
|
||||
glBufferData( GL_ARRAY_BUFFER, m_nVertexCount * sizeof( CVertNormTex ), m_pVNT.data(), GL_STATIC_DRAW );
|
||||
#endif
|
||||
// WriteLog("Assigned VBO number "+AnsiString(m_nVBOVertices)+", vertices:
|
||||
// "+AnsiString(m_nVertexCount));
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
if (del)
|
||||
SafeDeleteArray(m_pVNT); // wierzchołki już się nie przydadzą
|
||||
#else
|
||||
m_pVNT.clear();
|
||||
#endif
|
||||
};
|
||||
|
||||
void CMesh::Clear()
|
||||
{ // niewirtualne zwolnienie zasobów przez sprzątacz albo destruktor
|
||||
// inna nazwa, żeby nie mieszało się z funkcją wirtualną sprzątacza
|
||||
if (m_nVBOVertices) // jeśli było coś rezerwowane
|
||||
{
|
||||
glDeleteBuffers(1, &m_nVBOVertices); // Free The Memory
|
||||
// WriteLog("Released VBO number "+AnsiString(m_nVBOVertices));
|
||||
}
|
||||
m_nVBOVertices = 0;
|
||||
m_nVertexCount = -1; // do ponownego zliczenia
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
SafeDeleteArray(m_pVNT); // usuwanie tablic, gdy były użyte do Vertex Array
|
||||
#else
|
||||
m_pVNT.clear();
|
||||
#endif
|
||||
};
|
||||
|
||||
bool CMesh::StartVBO()
|
||||
{ // początek rysowania elementów z VBO
|
||||
|
||||
if (m_nVertexCount <= 0)
|
||||
return false; // nie ma nic do rysowania w ten sposób
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (m_nVBOVertices)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
|
||||
glVertexPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) ); // pozycje
|
||||
glNormalPointer( GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // normalne
|
||||
glTexCoordPointer( 2, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 24 ); // wierzchołki
|
||||
return true; // można rysować z VBO
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
bool CMesh::StartColorVBO()
|
||||
{ // początek rysowania punktów świecących z VBO
|
||||
|
||||
if (m_nVertexCount <= 0)
|
||||
return false; // nie ma nic do rysowania w ten sposób
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
if (m_nVBOVertices)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_nVBOVertices);
|
||||
glVertexPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) ); // pozycje
|
||||
// glColorPointer(3,GL_UNSIGNED_BYTE,sizeof(CVertNormTex),((char*)NULL)+12); //kolory
|
||||
glColorPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // kolory
|
||||
return true; // można rysować z VBO
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
void CMesh::EndVBO()
|
||||
{ // koniec użycia VBO
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
// glBindBuffer(GL_ARRAY_BUFFER,0); //takie coś psuje, mimo iż polecali użyć
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Ra: to na przyszłość
|
||||
};
|
||||
|
||||
43
VBO.h
43
VBO.h
@@ -11,48 +11,9 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "openglgeometrybank.h"
|
||||
|
||||
#define EU07_USE_OLD_VERTEXBUFFER
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/*
|
||||
class CVertNormTex
|
||||
class CMesh
|
||||
{
|
||||
public:
|
||||
float x = 0.0; // X wierzchołka
|
||||
float y = 0.0; // Y wierzchołka
|
||||
float z = 0.0; // Z wierzchołka
|
||||
float nx = 0.0; // X wektora normalnego
|
||||
float ny = 0.0; // Y wektora normalnego
|
||||
float nz = 0.0; // Z wektora normalnego
|
||||
float u = 0.0; // U mapowania
|
||||
float v = 0.0; // V mapowania
|
||||
|
||||
void deserialize(std::istream&);
|
||||
void serialize(std::ostream&);
|
||||
};
|
||||
*/
|
||||
typedef basic_vertex CVertNormTex;
|
||||
|
||||
class CMesh
|
||||
{ // wsparcie dla VBO
|
||||
public:
|
||||
CMesh();
|
||||
~CMesh();
|
||||
void MakeArray(int n); // tworzenie tablicy z elementami VNT
|
||||
void BuildVBOs(bool del = true); // zamiana tablic na VBO
|
||||
void Clear(); // zwolnienie zasobów
|
||||
bool StartVBO();
|
||||
void EndVBO();
|
||||
bool StartColorVBO();
|
||||
|
||||
int m_nVertexCount; // liczba wierzchołków
|
||||
#ifdef EU07_USE_OLD_VERTEXBUFFER
|
||||
CVertNormTex *m_pVNT;
|
||||
#else
|
||||
std::vector<CVertNormTex> m_pVNT;
|
||||
#endif
|
||||
unsigned int m_nVBOVertices; // numer VBO z wierzchołkami
|
||||
|
||||
geometrybank_handle m_geometrybank;
|
||||
|
||||
bool m_geometrycreated { false };
|
||||
};
|
||||
|
||||
40
World.cpp
40
World.cpp
@@ -1267,7 +1267,7 @@ TWorld::Render_Cab() {
|
||||
}
|
||||
|
||||
TDynamicObject *dynamic = Train->Dynamic();
|
||||
TSubModel::iInstance = reinterpret_cast<size_t>( dynamic );
|
||||
TSubModel::iInstance = reinterpret_cast<std::size_t>( dynamic );
|
||||
|
||||
if( ( true == FreeFlyModeFlag )
|
||||
|| ( false == dynamic->bDisplayCab )
|
||||
@@ -1275,8 +1275,6 @@ TWorld::Render_Cab() {
|
||||
// ABu: Rendering kabiny jako ostatniej, zeby bylo widac przez szyby, tylko w widoku ze srodka
|
||||
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ą
|
||||
@@ -1651,7 +1649,7 @@ TWorld::Update_UI() {
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F8 ) : {
|
||||
|
||||
// gfx renderer data
|
||||
uitextline1 =
|
||||
"Draw range x " + to_string( Global::fDistanceFactor, 1 )
|
||||
+ "; FPS: " + to_string( Timer::GetFPS(), 2 );
|
||||
@@ -1659,28 +1657,16 @@ TWorld::Update_UI() {
|
||||
uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
|
||||
}
|
||||
uitextline1 +=
|
||||
", sectors: " + to_string( Ground.iRendered )
|
||||
+ "/" + to_string( Global::iSegmentsRendered )
|
||||
", sectors: " + std::to_string( GfxRenderer.m_drawcount )
|
||||
+ "/" + std::to_string( Global::iSegmentsRendered )
|
||||
+ "; FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F9 ) : {
|
||||
// informacja o wersji, sposobie wyświetlania i błędach OpenGL
|
||||
uitextline1 = "MaSzyna " + Global::asVersion; // informacja o wersji
|
||||
if( Global::iMultiplayer ) {
|
||||
uitextline1 += " (multiplayer mode is active)";
|
||||
}
|
||||
|
||||
uitextline2 =
|
||||
std::string("Rendering mode: ")
|
||||
std::string( "Rendering mode: " )
|
||||
+ ( Global::bUseVBO ?
|
||||
"VBO" :
|
||||
"Display Lists" )
|
||||
+ ". "
|
||||
+ GfxRenderer.Info();
|
||||
|
||||
+ ". ";
|
||||
// dump last opengl error, if any
|
||||
GLenum glerror = ::glGetError();
|
||||
if( glerror != GL_NO_ERROR ) {
|
||||
@@ -1689,10 +1675,22 @@ TWorld::Update_UI() {
|
||||
Global::LastGLError = std::to_string( glerror ) + " (" + glerrorstring + ")";
|
||||
}
|
||||
if( false == Global::LastGLError.empty() ) {
|
||||
uitextline3 =
|
||||
uitextline2 +=
|
||||
"Last openGL error: "
|
||||
+ Global::LastGLError;
|
||||
}
|
||||
// renderer stats
|
||||
uitextline3 = GfxRenderer.Info();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case( GLFW_KEY_F9 ) : {
|
||||
// informacja o wersji
|
||||
uitextline1 = "MaSzyna " + Global::asVersion; // informacja o wersji
|
||||
if( Global::iMultiplayer ) {
|
||||
uitextline1 += " (multiplayer mode is active)";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -48,13 +48,13 @@ basic_vertex::deserialize( std::istream &s ) {
|
||||
|
||||
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk
|
||||
geometry_handle
|
||||
geometry_bank::create( vertex_array &Vertices, int const Type ) {
|
||||
geometry_bank::create( vertex_array &Vertices, unsigned int const Type, unsigned int const Streams ) {
|
||||
|
||||
if( true == Vertices.empty() ) { return geometry_handle( 0, 0 ); }
|
||||
|
||||
m_chunks.emplace_back( Vertices, Type );
|
||||
m_chunks.emplace_back( Vertices, Type, Streams );
|
||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
||||
geometry_handle chunkhandle{ 0, m_chunks.size() };
|
||||
geometry_handle chunkhandle { 0, static_cast<std::uint32_t>(m_chunks.size()) };
|
||||
// template method
|
||||
create_( chunkhandle );
|
||||
// all done
|
||||
|
||||
@@ -18,14 +18,30 @@ http://mozilla.org/MPL/2.0/.
|
||||
#endif
|
||||
|
||||
struct basic_vertex {
|
||||
|
||||
glm::vec3 position; // 3d space
|
||||
glm::vec3 normal; // 3d space
|
||||
glm::vec2 texture; // uv space
|
||||
|
||||
basic_vertex() = default;
|
||||
basic_vertex( glm::vec3 const&Position, glm::vec3 const &Normal, glm::vec2 const &Texture ) :
|
||||
position( Position ), normal( Normal ), texture( Texture )
|
||||
{}
|
||||
void serialize( std::ostream& );
|
||||
void deserialize( std::istream& );
|
||||
};
|
||||
|
||||
// data streams carried in a vertex
|
||||
enum stream {
|
||||
position = 0x1,
|
||||
normal = 0x2,
|
||||
color = 0x4, // currently normal and colour streams are stored in the same slot, and mutually exclusive
|
||||
texture = 0x8
|
||||
};
|
||||
|
||||
unsigned int const basic_streams { stream::position | stream::normal | stream::texture };
|
||||
unsigned int const color_streams{ stream::position | stream::color | stream::texture };
|
||||
|
||||
typedef std::vector<basic_vertex> vertex_array;
|
||||
|
||||
// generic geometry bank class, allows storage, update and drawing of geometry chunks
|
||||
@@ -40,12 +56,20 @@ struct geometry_handle {
|
||||
{}
|
||||
// methods
|
||||
inline
|
||||
operator std::uint32_t() const {
|
||||
return bank << 12 | chunk; }
|
||||
operator std::uint64_t() const {
|
||||
/*
|
||||
return bank << 14 | chunk; }
|
||||
*/
|
||||
return bank << 32 | chunk; }
|
||||
|
||||
// members
|
||||
/*
|
||||
std::uint32_t
|
||||
bank : 20, // 1 mil banks
|
||||
chunk : 12; // 4 k chunks per bank
|
||||
bank : 18, // 250k banks
|
||||
chunk : 14; // 16k chunks per bank
|
||||
*/
|
||||
std::uint32_t bank;
|
||||
std::uint32_t chunk;
|
||||
};
|
||||
|
||||
class geometry_bank {
|
||||
@@ -62,7 +86,7 @@ public:
|
||||
// methods:
|
||||
// creates a new geometry chunk of specified type from supplied vertex data. returns: handle to the chunk or NULL
|
||||
geometry_handle
|
||||
create( vertex_array &Vertices, int const Type );
|
||||
create( vertex_array &Vertices, unsigned int const Type, unsigned int const Streams = stream::position | stream::normal | stream::texture );
|
||||
// replaces data of specified chunk with the supplied vertex data, starting from specified offset
|
||||
bool
|
||||
replace( vertex_array &Vertices, geometry_handle const &Geometry, std::size_t const Offset = 0 );
|
||||
@@ -83,11 +107,12 @@ public:
|
||||
protected:
|
||||
// types:
|
||||
struct geometry_chunk {
|
||||
int type; // kind of geometry used by the chunk
|
||||
unsigned int streams; // data streams carried by vertices
|
||||
unsigned int type; // kind of geometry used by the chunk
|
||||
vertex_array vertices; // geometry data
|
||||
|
||||
geometry_chunk( vertex_array &Vertices, int const Type ) :
|
||||
vertices( Vertices ), type( Type )
|
||||
geometry_chunk( vertex_array &Vertices, unsigned int const Type, unsigned int const Streams ) :
|
||||
vertices( Vertices ), type( Type ), streams( Streams )
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -121,9 +146,14 @@ private:
|
||||
class opengl_vbogeometrybank : public geometry_bank {
|
||||
|
||||
public:
|
||||
// methods:
|
||||
// destructor
|
||||
~opengl_vbogeometrybank() {
|
||||
delete_buffer(); }
|
||||
// methods:
|
||||
static
|
||||
void
|
||||
reset() {
|
||||
m_activebuffer = 0; }
|
||||
|
||||
private:
|
||||
// types:
|
||||
@@ -217,6 +247,12 @@ public:
|
||||
// draws geometry stored in specified chunk
|
||||
void
|
||||
draw( geometry_handle const &Geometry );
|
||||
template <typename Iterator_>
|
||||
void
|
||||
draw( Iterator_ First, Iterator_ Last ) {
|
||||
while( First != Last ) {
|
||||
draw( *First );
|
||||
++First; } }
|
||||
// provides direct access to vertex data of specfied chunk
|
||||
vertex_array const &
|
||||
vertices( geometry_handle const &Geometry ) const;
|
||||
|
||||
12
parser.cpp
12
parser.cpp
@@ -30,6 +30,9 @@ cParser::cParser( std::string const &Stream, buffertype const Type, std::string
|
||||
// mComments.insert(commentmap::value_type("--","\n")); //Ra: to chyba nie używane
|
||||
// store to calculate sub-sequent includes from relative path
|
||||
mPath = Path;
|
||||
if( Type == buffertype::buffer_FILE ) {
|
||||
mFile = Stream;
|
||||
}
|
||||
// reset pointers and attach proper type of buffer
|
||||
switch (Type)
|
||||
{
|
||||
@@ -263,8 +266,15 @@ std::size_t cParser::count() {
|
||||
return count - 1;
|
||||
}
|
||||
|
||||
|
||||
void cParser::addCommentStyle( std::string const &Commentstart, std::string const &Commentend ) {
|
||||
|
||||
mComments.insert( commentmap::value_type(Commentstart, Commentend) );
|
||||
}
|
||||
|
||||
// returns name of currently open file, or empty string for text type stream
|
||||
std::string
|
||||
cParser::Name() {
|
||||
|
||||
if( mIncludeParser ) { return mIncludeParser->Name(); }
|
||||
else { return mPath + mFile; }
|
||||
}
|
||||
|
||||
4
parser.h
4
parser.h
@@ -85,19 +85,21 @@ class cParser //: public std::stringstream
|
||||
static std::size_t countTokens( std::string const &Stream, std::string Path = "" );
|
||||
// add custom definition of text which should be ignored when retrieving tokens
|
||||
void addCommentStyle( std::string const &Commentstart, std::string const &Commentend );
|
||||
// returns name of currently open file, or empty string for text type stream
|
||||
std::string Name();
|
||||
|
||||
private:
|
||||
// methods:
|
||||
std::string readToken(bool ToLower = true, const char *Break = "\n\r\t ;");
|
||||
std::string readQuotes( char const Quote = '\"' );
|
||||
std::string readComment( std::string const &Break = "\n\r\t ;" );
|
||||
// std::string trtest;
|
||||
bool findQuotes( std::string &String );
|
||||
bool trimComments( std::string &String );
|
||||
std::size_t count();
|
||||
// members:
|
||||
bool LoadTraction; // load traction?
|
||||
std::istream *mStream; // relevant kind of buffer is attached on creation.
|
||||
std::string mFile; // name of the open file, if any
|
||||
std::string mPath; // path to open stream, for relative path lookups.
|
||||
std::streamoff mSize; // size of open stream, for progress report.
|
||||
typedef std::map<std::string, std::string> commentmap;
|
||||
|
||||
564
renderer.cpp
564
renderer.cpp
@@ -39,7 +39,8 @@ opengl_camera::visible( TDynamicObject const *Dynamic ) const {
|
||||
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;
|
||||
// we're giving vehicles some extra padding, to allow for things like shared bogeys extending past the main body
|
||||
float const radius = glm::length( diagonal ) * 0.65f;
|
||||
|
||||
return ( m_frustum.sphere_inside( Dynamic->GetPosition(), radius ) > 0.0f );
|
||||
}
|
||||
@@ -47,10 +48,7 @@ opengl_camera::visible( TDynamicObject const *Dynamic ) const {
|
||||
bool
|
||||
opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
|
||||
if( false == Init_caps() ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
if( false == Init_caps() ) { return false; }
|
||||
|
||||
m_window = Window;
|
||||
|
||||
@@ -111,11 +109,21 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
}
|
||||
// preload some common textures
|
||||
WriteLog( "Loading common gfx data..." );
|
||||
m_glaretextureid = GetTextureId( "fx\\lightglare", szTexturePath );
|
||||
m_suntextureid = GetTextureId( "fx\\sun", szTexturePath );
|
||||
m_moontextureid = GetTextureId( "fx\\moon", szTexturePath );
|
||||
m_glaretexture = GetTextureId( "fx\\lightglare", szTexturePath );
|
||||
m_suntexture = GetTextureId( "fx\\sun", szTexturePath );
|
||||
m_moontexture = GetTextureId( "fx\\moon", szTexturePath );
|
||||
WriteLog( "...gfx data pre-loading done" );
|
||||
|
||||
// prepare basic geometry chunks
|
||||
auto const geometrybank = m_geometry.create_bank();
|
||||
float const size = 2.5f;
|
||||
m_billboardgeometry = m_geometry.create_chunk(
|
||||
vertex_array{
|
||||
{ { -size, size, 0.0f }, glm::vec3(), { 1.0f, 1.0f } },
|
||||
{ { size, size, 0.0f }, glm::vec3(), { 0.0f, 1.0f } },
|
||||
{ { -size, -size, 0.0f }, glm::vec3(), { 1.0f, 0.0f } },
|
||||
{ { size, -size, 0.0f }, glm::vec3(), { 0.0f, 0.0f } } },
|
||||
geometrybank,
|
||||
GL_TRIANGLE_STRIP );
|
||||
// prepare debug mode objects
|
||||
m_quadric = gluNewQuadric();
|
||||
gluQuadricNormals( m_quadric, GLU_FLAT );
|
||||
@@ -157,6 +165,7 @@ opengl_renderer::Render() {
|
||||
|
||||
// accumulate last 20 frames worth of render time (cap at 1000 fps to prevent calculations going awry)
|
||||
m_drawtime = std::max( 20.0f, 0.95f * m_drawtime + std::chrono::duration_cast<std::chrono::milliseconds>( ( std::chrono::steady_clock::now() - timestart ) ).count());
|
||||
m_drawcount = m_drawqueue.size();
|
||||
}
|
||||
|
||||
UILayer.render();
|
||||
@@ -189,6 +198,10 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
else { ::glDisable( GL_FOG ); }
|
||||
|
||||
Environment->m_skydome.Render();
|
||||
if( true == Global::bUseVBO ) {
|
||||
// skydome uses a custom vbo which could potentially confuse the main geometry system. hardly elegant but, eh
|
||||
opengl_vbogeometrybank::reset();
|
||||
}
|
||||
Environment->m_stars.render();
|
||||
|
||||
float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f;
|
||||
@@ -213,7 +226,7 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
|
||||
// sun
|
||||
{
|
||||
Bind( m_suntextureid );
|
||||
Bind( m_suntexture );
|
||||
::glColor4f( suncolor.x, suncolor.y, suncolor.z, 1.0f );
|
||||
auto const sunvector = Environment->m_sun.getDirection();
|
||||
auto const sunposition = modelview * glm::vec4( sunvector.x, sunvector.y, sunvector.z, 1.0f );
|
||||
@@ -234,7 +247,7 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
}
|
||||
// moon
|
||||
{
|
||||
Bind( m_moontextureid );
|
||||
Bind( m_moontexture );
|
||||
float3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
|
||||
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 1.0 - Global::fLuminance * 0.5 ) );
|
||||
|
||||
@@ -412,7 +425,8 @@ opengl_renderer::Render( TGround *Ground ) {
|
||||
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
|
||||
m_drawqueue.clear();
|
||||
|
||||
Math3D::vector3 direction;
|
||||
for( k = 0; k < Global::iSegmentsRendered; ++k ) // sektory w kolejności odległości
|
||||
{ // przerobione na użycie SectorOrder
|
||||
@@ -436,37 +450,14 @@ opengl_renderer::Render( TGround *Ground ) {
|
||||
if( ( tmp = Ground->FastGetSubRect( i + c, j + r ) ) != nullptr ) {
|
||||
if( tmp->iNodeCount ) {
|
||||
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
|
||||
Ground->pRendered[ Ground->iRendered++ ] = tmp; // tworzenie listy sektorów do renderowania
|
||||
m_drawqueue.emplace_back( tmp );
|
||||
}
|
||||
}
|
||||
} 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 != nullptr )
|
||||
&& ( Global::pTerrainCompact->pModel != nullptr ) ) {
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
Global::pTerrainCompact->TerrainRenderVBO( TGroundRect::iFrameNumber );
|
||||
#endif
|
||||
// TODO: remap geometry of terrain cells to allow camera-centric rendering
|
||||
::glPushMatrix();
|
||||
::glTranslated( -Global::pCameraPosition.x, -Global::pCameraPosition.y, -Global::pCameraPosition.z );
|
||||
TSubModel *submodel = Global::pTerrainCompact->pModel->Root;
|
||||
while( submodel != nullptr ) {
|
||||
if( submodel->iVisible == TGroundRect::iFrameNumber ) {
|
||||
// tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
|
||||
Render( submodel ); // sub kolejne (Next) się nie wyrenderują
|
||||
}
|
||||
submodel = submodel->NextGet();
|
||||
}
|
||||
::glPopMatrix();
|
||||
}
|
||||
}
|
||||
*/
|
||||
// renderowanie nieprzezroczystych
|
||||
for( i = 0; i < Ground->iRendered; ++i ) {
|
||||
Render( Ground->pRendered[ i ] );
|
||||
|
||||
for( auto subcell : m_drawqueue ) {
|
||||
Render( subcell );
|
||||
}
|
||||
// regular render takes care of all solid geometry present in the scene, thus we can launch alpha parts render here
|
||||
return Render_Alpha( Ground );
|
||||
@@ -478,69 +469,23 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
|
||||
|
||||
bool result { false }; // will be true if we do any rendering
|
||||
|
||||
// TODO: unify render paths
|
||||
if( Global::bUseVBO ) {
|
||||
if( Groundcell->iLastDisplay != Groundcell->iFrameNumber ) {
|
||||
// tylko jezeli dany kwadrat nie był jeszcze renderowany
|
||||
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
|
||||
|
||||
if ( Groundcell->iLastDisplay != Groundcell->iFrameNumber) {
|
||||
// tylko jezeli dany kwadrat nie był jeszcze renderowany
|
||||
Groundcell->LoadNodes(); // ewentualne tworzenie siatek
|
||||
|
||||
if( ( Groundcell->nRenderRect != nullptr )
|
||||
&& ( true == Groundcell->StartVBO() ) ) {
|
||||
// nieprzezroczyste trójkąty kwadratu kilometrowego
|
||||
for( TGroundNode *node = Groundcell->nRenderRect; node; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
Groundcell->EndVBO();
|
||||
if( Groundcell->nRenderRect != nullptr ) {
|
||||
// nieprzezroczyste trójkąty kwadratu kilometrowego
|
||||
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
if( Groundcell->nTerrain ) {
|
||||
|
||||
Render( Groundcell->nTerrain );
|
||||
}
|
||||
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
|
||||
result = true;
|
||||
}
|
||||
if( Groundcell->nTerrain ) {
|
||||
|
||||
Render( Groundcell->nTerrain );
|
||||
}
|
||||
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
::glPushMatrix();
|
||||
auto const &cellorigin = Groundcell->m_area.center;
|
||||
// TODO: unify all math objects
|
||||
auto const originoffset = Math3D::vector3( cellorigin.x, cellorigin.y, cellorigin.z ) - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
if (Groundcell->iLastDisplay != Groundcell->iFrameNumber)
|
||||
{ // tylko jezeli dany kwadrat nie był jeszcze renderowany
|
||||
// for (TGroundNode* node=pRender;node;node=node->pNext3)
|
||||
// node->Render(); //nieprzezroczyste trójkąty kwadratu kilometrowego
|
||||
if ( Groundcell->nRender)
|
||||
{ //łączenie trójkątów w jedną listę - trochę wioska
|
||||
if (!Groundcell->nRender->DisplayListID || ( Groundcell->nRender->iVersion != Global::iReCompile))
|
||||
{ // jeżeli nie skompilowany, kompilujemy wszystkie trójkąty w jeden
|
||||
Groundcell->nRender->fSquareRadius = 5000.0 * 5000.0; // aby agregat nigdy nie znikał
|
||||
Groundcell->nRender->DisplayListID = glGenLists(1);
|
||||
glNewList( Groundcell->nRender->DisplayListID, GL_COMPILE);
|
||||
Groundcell->nRender->iVersion = Global::iReCompile; // aktualna wersja siatek
|
||||
auto const origin = glm::dvec3( Groundcell->m_area.center );
|
||||
for (TGroundNode *node = Groundcell->nRender; node; node = node->nNext3) // następny tej grupy
|
||||
node->Compile(origin, true);
|
||||
glEndList();
|
||||
}
|
||||
Render( Groundcell->nRender ); // nieprzezroczyste trójkąty kwadratu kilometrowego
|
||||
}
|
||||
// submodels geometry is world-centric, so at least for the time being we need to pop the stack early
|
||||
::glPopMatrix();
|
||||
|
||||
if( Groundcell->nTerrain ) { Render( Groundcell->nTerrain ); }
|
||||
|
||||
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
::glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -551,32 +496,21 @@ opengl_renderer::Render( TSubRect *Groundsubcell ) {
|
||||
|
||||
TGroundNode *node;
|
||||
// nieprzezroczyste obiekty terenu
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( Groundsubcell->StartVBO() ) {
|
||||
for( node = Groundsubcell->nRenderRect; node; node = node->nNext3 ) {
|
||||
if( node->iVboPtr >= 0 ) {
|
||||
Render( node );
|
||||
}
|
||||
}
|
||||
Groundsubcell->EndVBO();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
for( node = Groundsubcell->nRenderRect; node; node = node->nNext3 ) {
|
||||
Render( node ); // nieprzezroczyste obiekty terenu
|
||||
}
|
||||
for( node = Groundsubcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
// nieprzezroczyste obiekty (oprócz pojazdów)
|
||||
for( node = Groundsubcell->nRender; node; node = node->nNext3 )
|
||||
for( node = Groundsubcell->nRender; node != nullptr; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
// nieprzezroczyste z mieszanych modeli
|
||||
for( node = Groundsubcell->nRenderMixed; node; node = node->nNext3 )
|
||||
for( node = Groundsubcell->nRenderMixed; node != nullptr; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
// nieprzezroczyste fragmenty pojazdów na torach
|
||||
for( int j = 0; j < Groundsubcell->iTracks; ++j )
|
||||
for( int j = 0; j < Groundsubcell->iTracks; ++j ) {
|
||||
Groundsubcell->tTracks[ j ]->RenderDyn();
|
||||
}
|
||||
#ifdef EU07_SCENERY_EDITOR
|
||||
// memcells
|
||||
if( DebugModeFlag ) {
|
||||
@@ -590,9 +524,9 @@ opengl_renderer::Render( TSubRect *Groundsubcell ) {
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( TGroundNode *Node ) {
|
||||
|
||||
/*
|
||||
Node->SetLastUsage( Timer::GetSimulationTime() );
|
||||
|
||||
*/
|
||||
switch (Node->iType)
|
||||
{ // obiekty renderowane niezależnie od odległości
|
||||
case TP_SUBMODEL:
|
||||
@@ -611,96 +545,58 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Node->iType)
|
||||
{
|
||||
case TP_TRACK: {
|
||||
switch (Node->iType) {
|
||||
|
||||
if( Global::bUseVBO && ( Node->iNumVerts <= 0 ) ) {
|
||||
return false;
|
||||
}
|
||||
case TP_TRACK: {
|
||||
// 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 ) {
|
||||
// vbo render path
|
||||
Node->pTrack->RaRenderVBO( Node->iVboPtr );
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
Node->pTrack->Render();
|
||||
}
|
||||
// render
|
||||
Render( Node->pTrack );
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
return true;
|
||||
}
|
||||
|
||||
case TP_MODEL: {
|
||||
Node->Model->Render( Node->pCenter - Global::pCameraPosition );
|
||||
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(Node->m_rootposition);
|
||||
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
|
||||
::glColor4fv(
|
||||
glm::value_ptr(
|
||||
glm::vec4(
|
||||
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ),
|
||||
std::min(
|
||||
1.0,
|
||||
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) );
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
|
||||
// render
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumPts );
|
||||
::glPopMatrix();
|
||||
}
|
||||
else {
|
||||
::glCallList( Node->DisplayListID );
|
||||
}
|
||||
// post-render cleanup
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
case GL_LINES: {
|
||||
if( ( Node->m_geometry == NULL )
|
||||
|| ( Node->fLineThickness > 0.0 ) ) {
|
||||
return false;
|
||||
}
|
||||
// setup
|
||||
// w zaleznosci od koloru swiatla
|
||||
::glColor4fv(
|
||||
glm::value_ptr(
|
||||
glm::vec4(
|
||||
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ),
|
||||
std::min(
|
||||
1.0,
|
||||
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) );
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
// render
|
||||
m_geometry.draw( Node->m_geometry );
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// GL_TRIANGLE etc
|
||||
if( ( Global::bUseVBO ?
|
||||
Node->iVboPtr < 0 :
|
||||
Node->DisplayListID == 0 ) ) {
|
||||
|
||||
case GL_TRIANGLES: {
|
||||
if( ( Node->m_geometry == NULL )
|
||||
|| ( ( Node->iFlags & 0x10 ) == 0 ) ) {
|
||||
return false;
|
||||
}
|
||||
// setup
|
||||
@@ -708,23 +604,25 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
||||
|
||||
Bind( Node->TextureID );
|
||||
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
// render
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
::glDrawArrays( Node->iType, Node->iVboPtr, Node->iNumVerts );
|
||||
::glPopMatrix();
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
::glCallList( Node->DisplayListID );
|
||||
}
|
||||
m_geometry.draw( Node->m_geometry );
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case TP_MEMCELL: {
|
||||
Render( Node->MemCell );
|
||||
return true;
|
||||
}
|
||||
|
||||
default: { break; }
|
||||
}
|
||||
// in theory we shouldn't ever get here but, eh
|
||||
return false;
|
||||
@@ -946,7 +844,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
::glDisableClientState( GL_NORMAL_ARRAY );
|
||||
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
::glEnableClientState( GL_COLOR_ARRAY );
|
||||
::glColorPointer( 3, GL_FLOAT, sizeof( CVertNormTex ), static_cast<char *>( nullptr ) + 12 ); // kolory
|
||||
::glColorPointer( 3, GL_FLOAT, sizeof( basic_vertex ), static_cast<char *>( nullptr ) + 12 ); // kolory
|
||||
|
||||
::glDrawArrays( GL_POINTS, Submodel->iVboPtr, Submodel->iNumVerts );
|
||||
|
||||
@@ -978,6 +876,28 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
Render( Submodel->Next ); // dalsze rekurencyjnie
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Render( TTrack *Track ) {
|
||||
|
||||
if( ( Track->TextureID1 == 0 )
|
||||
&& ( Track->TextureID2 == 0 ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Track->EnvironmentSet();
|
||||
|
||||
if( Track->TextureID1 != 0 ) {
|
||||
Bind( Track->TextureID1 );
|
||||
m_geometry.draw( std::begin( Track->Geometry1 ), std::end( Track->Geometry1 ) );
|
||||
}
|
||||
if( Track->TextureID2 != 0 ) {
|
||||
Bind( Track->TextureID2 );
|
||||
m_geometry.draw( std::begin( Track->Geometry2 ), std::end( Track->Geometry2 ) );
|
||||
}
|
||||
|
||||
Track->EnvironmentReset();
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Render( TMemCell *Memcell ) {
|
||||
|
||||
@@ -999,7 +919,6 @@ opengl_renderer::Render( TMemCell *Memcell ) {
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TGround *Ground ) {
|
||||
|
||||
// legacy version of the code:
|
||||
::glEnable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.04f ); // im mniejsza wartość, tym większa ramka, domyślnie 0.1f
|
||||
::glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
@@ -1007,54 +926,30 @@ opengl_renderer::Render_Alpha( TGround *Ground ) {
|
||||
TGroundNode *node;
|
||||
TSubRect *tmp;
|
||||
// Ra: renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
|
||||
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
|
||||
{ // przezroczyste trójkąty w oddzielnym cyklu przed modelami
|
||||
tmp = Ground->pRendered[ i ];
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( tmp->StartVBO() ) {
|
||||
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
||||
if( node->iVboPtr >= 0 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
}
|
||||
tmp->EndVBO();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
for( auto subcell = std::rbegin( m_drawqueue ); subcell != std::rend( m_drawqueue ); ++subcell ) {
|
||||
// przezroczyste trójkąty w oddzielnym cyklu przed modelami
|
||||
tmp = *subcell;
|
||||
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
}
|
||||
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
|
||||
for( auto subcell = std::rbegin( m_drawqueue ); subcell != std::rend( m_drawqueue ); ++subcell )
|
||||
{ // renderowanie przezroczystych modeli oraz pojazdów
|
||||
Render_Alpha( Ground->pRendered[ i ] );
|
||||
Render_Alpha( *subcell );
|
||||
}
|
||||
|
||||
::glDisable( GL_LIGHTING ); // linie nie powinny świecić
|
||||
|
||||
for( int i = Ground->iRendered - 1; i >= 0; --i ) // od najdalszych
|
||||
{ // druty na końcu, żeby się nie robiły białe plamy na tle lasu
|
||||
tmp = Ground->pRendered[ i ];
|
||||
if( Global::bUseVBO ) {
|
||||
// vbo render path
|
||||
if( tmp->StartVBO() ) {
|
||||
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
tmp->EndVBO();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// display list render path
|
||||
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node ); // druty
|
||||
}
|
||||
for( auto subcell = std::rbegin( m_drawqueue ); subcell != std::rend( m_drawqueue ); ++subcell ) {
|
||||
// druty na końcu, żeby się nie robiły białe plamy na tle lasu
|
||||
tmp = *subcell;
|
||||
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
|
||||
Render_Alpha( node );
|
||||
}
|
||||
}
|
||||
|
||||
::glEnable( GL_LIGHTING );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1091,9 +986,9 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
// 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 ) ) ) {
|
||||
@@ -1103,7 +998,6 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
switch (Node->iType)
|
||||
{
|
||||
case TP_TRACTION: {
|
||||
// TODO: unify the render code after generic buffers are in place
|
||||
if( Node->bVisible ) {
|
||||
// rysuj jesli sa druty i nie zerwana
|
||||
if( ( Node->hvTraction->Wires == 0 )
|
||||
@@ -1111,11 +1005,6 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
return false;
|
||||
}
|
||||
// setup
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
Bind( NULL );
|
||||
if( !Global::bSmoothTraction ) {
|
||||
// na liniach kiepsko wygląda - robi gradient
|
||||
::glDisable( GL_LINE_SMOOTH );
|
||||
@@ -1129,16 +1018,23 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
auto const color { Node->hvTraction->wire_color() };
|
||||
::glColor4f( color.r, color.g, color.b, linealpha );
|
||||
|
||||
Bind( NULL );
|
||||
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
// render
|
||||
m_geometry.draw( Node->hvTraction->m_geometry );
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
|
||||
::glLineWidth( 1.0 );
|
||||
if( !Global::bSmoothTraction ) {
|
||||
::glEnable( GL_LINE_SMOOTH );
|
||||
}
|
||||
|
||||
::glPopMatrix();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@@ -1149,102 +1045,75 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
Node->Model->RenderAlpha( Node->pCenter - Global::pCameraPosition );
|
||||
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(Node->m_rootposition);
|
||||
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
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
// w zaleznosci od koloru swiatla
|
||||
::glColor4fv(
|
||||
glm::value_ptr(
|
||||
glm::vec4(
|
||||
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ),
|
||||
std::min(
|
||||
1.0,
|
||||
1000.0 * 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 );
|
||||
}
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
result = true;
|
||||
case GL_LINES: {
|
||||
if( ( Node->m_geometry == NULL )
|
||||
|| ( Node->fLineThickness < 0.0 ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// GL_TRIANGLE etc
|
||||
// setup
|
||||
// w zaleznosci od koloru swiatla
|
||||
::glColor4fv(
|
||||
glm::value_ptr(
|
||||
glm::vec4(
|
||||
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ),
|
||||
std::min(
|
||||
1.0,
|
||||
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) );
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
// render
|
||||
m_geometry.draw( Node->m_geometry );
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case GL_TRIANGLES: {
|
||||
if( ( Node->m_geometry == NULL )
|
||||
|| ( ( Node->iFlags & 0x20 ) == 0 ) ) {
|
||||
return false;
|
||||
}
|
||||
// setup
|
||||
#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
|
||||
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
|
||||
|
||||
Bind( Node->TextureID );
|
||||
|
||||
::glPushMatrix();
|
||||
auto const originoffset = Node->m_rootposition - Global::pCameraPosition;
|
||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||
|
||||
// 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;
|
||||
}
|
||||
m_geometry.draw( Node->m_geometry );
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
#ifdef _PROBLEND
|
||||
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
|
||||
{
|
||||
::glEnable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.04f );
|
||||
}
|
||||
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
|
||||
{
|
||||
::glEnable( GL_BLEND );
|
||||
::glAlphaFunc( GL_GREATER, 0.04f );
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
default: { break; }
|
||||
}
|
||||
// in theory we shouldn't ever get here but, eh
|
||||
return false;
|
||||
@@ -1253,10 +1122,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
|
||||
if( false == Dynamic->renderme ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
if( false == Dynamic->renderme ) { return false; }
|
||||
|
||||
// setup
|
||||
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
|
||||
@@ -1426,10 +1292,10 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
glarelevel = std::max( 0.0f, glarelevel - static_cast<float>(Global::fLuminance) );
|
||||
|
||||
if( glarelevel > 0.0f ) {
|
||||
|
||||
// setup
|
||||
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
|
||||
|
||||
Bind( m_glaretextureid );
|
||||
Bind( m_glaretexture );
|
||||
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], glarelevel );
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
@@ -1437,15 +1303,10 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity(); // macierz jedynkowa
|
||||
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
|
||||
::glRotated( atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt
|
||||
::glRotated( std::atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt
|
||||
|
||||
// TODO: turn the drawing instructions into a compiled call / array
|
||||
::glBegin( GL_TRIANGLE_STRIP );
|
||||
float const size = 2.5f;
|
||||
::glTexCoord2f( 1.0f, 1.0f ); ::glVertex3f( -size, size, 0.0f );
|
||||
::glTexCoord2f( 0.0f, 1.0f ); ::glVertex3f( size, size, 0.0f );
|
||||
::glTexCoord2f( 1.0f, 0.0f ); ::glVertex3f( -size, -size, 0.0f );
|
||||
::glTexCoord2f( 0.0f, 0.0f ); ::glVertex3f( size, -size, 0.0f );
|
||||
// main draw call
|
||||
m_geometry.draw( m_billboardgeometry );
|
||||
/*
|
||||
// NOTE: we could do simply...
|
||||
vec3 vertexPosition_worldspace =
|
||||
@@ -1454,8 +1315,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
+ CameraUp_worldspace * squareVertices.y * BillboardSize.y;
|
||||
// ...etc instead IF we had easy access to camera's forward and right vectors. TODO: check if Camera matrix is accessible
|
||||
*/
|
||||
::glEnd();
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
::glPopAttrib();
|
||||
}
|
||||
@@ -1557,8 +1417,12 @@ opengl_renderer::Update ( double const Deltatime ) {
|
||||
}
|
||||
|
||||
// TODO: add garbage collection and other less frequent works here
|
||||
if( DebugModeFlag )
|
||||
if( true == DebugModeFlag ) {
|
||||
m_debuginfo = m_textures.info();
|
||||
}
|
||||
else {
|
||||
m_debuginfo.clear();
|
||||
}
|
||||
};
|
||||
|
||||
// debug performance string
|
||||
|
||||
21
renderer.h
21
renderer.h
@@ -172,6 +172,7 @@ public:
|
||||
|
||||
// members
|
||||
GLenum static const sunlight{ GL_LIGHT0 };
|
||||
std::size_t m_drawcount { 0 };
|
||||
|
||||
private:
|
||||
// types
|
||||
@@ -194,6 +195,8 @@ private:
|
||||
Render( TSubRect *Groundsubcell );
|
||||
bool
|
||||
Render( TGroundNode *Node );
|
||||
void
|
||||
Render( TTrack *Track );
|
||||
void
|
||||
Render( TMemCell *Memcell );
|
||||
bool
|
||||
@@ -212,16 +215,18 @@ private:
|
||||
geometrybank_manager m_geometry;
|
||||
texture_manager m_textures;
|
||||
opengl_camera m_camera;
|
||||
rendermode renderpass{ rendermode::color };
|
||||
float m_drawrange{ 2500.0f }; // current drawing range
|
||||
float m_drawtime{ 1000.0f / 30.0f * 20.0f }; // start with presumed 'neutral' average of 30 fps
|
||||
double m_updateaccumulator{ 0.0 };
|
||||
rendermode renderpass { rendermode::color };
|
||||
float m_drawrange { 2500.0f }; // current drawing range
|
||||
float m_drawtime { 1000.0f / 30.0f * 20.0f }; // start with presumed 'neutral' average of 30 fps
|
||||
double m_updateaccumulator { 0.0 };
|
||||
std::string m_debuginfo;
|
||||
GLFWwindow *m_window{ nullptr };
|
||||
texture_handle m_glaretextureid{ -1 };
|
||||
texture_handle m_suntextureid{ -1 };
|
||||
texture_handle m_moontextureid{ -1 };
|
||||
GLFWwindow *m_window { nullptr };
|
||||
texture_handle m_glaretexture { -1 };
|
||||
texture_handle m_suntexture { -1 };
|
||||
texture_handle m_moontexture { -1 };
|
||||
geometry_handle m_billboardgeometry { 0, 0 };
|
||||
GLUquadricObj *m_quadric; // helper object for drawing debug mode scene elements
|
||||
std::vector< TSubRect* > m_drawqueue; // list of subcells to be drawn in current render pass
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user