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

build 170617. frustum based ground sector culling, fully view range based draw range limit, support for line width parameter for lines

This commit is contained in:
tmj-fstate
2017-06-18 01:16:28 +02:00
parent 0d805e8ba2
commit 34a899239f
11 changed files with 240 additions and 357 deletions

View File

@@ -39,7 +39,6 @@ http://mozilla.org/MPL/2.0/.
#include "world.h" #include "world.h"
#include "uilayer.h" #include "uilayer.h"
#define _PROBLEND 1
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
extern "C" extern "C"
@@ -1283,18 +1282,16 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
*parser >> token; *parser >> token;
} }
str = token; str = token;
#ifdef _PROBLEND
// PROBLEND Q: 13122011 - Szociu: 27012012
PROBLEND = true; // domyslnie uruchomione nowe wyświetlanie
tmp->PROBLEND = true; // odwolanie do tgroundnode, bo rendering jest w tej klasie
if (str.find('@') != std::string::npos) // sprawdza, czy w nazwie tekstury jest znak "@"
{
PROBLEND = false; // jeśli jest, wyswietla po staremu
tmp->PROBLEND = false;
}
#endif
tmp->TextureID = GfxRenderer.GetTextureId( str, szTexturePath ); tmp->TextureID = GfxRenderer.GetTextureId( str, szTexturePath );
tmp->iFlags = GfxRenderer.Texture(tmp->TextureID).has_alpha ? 0x220 : 0x210; // z usuwaniem
tmp->iFlags |= 200; // z usuwaniem
// remainder of legacy 'problend' system -- geometry assigned a texture with '@' in its name is treated as translucent, opaque otherwise
tmp->iFlags |= (
( ( str.find( '@' ) != std::string::npos )
&& ( true == GfxRenderer.Texture( tmp->TextureID ).has_alpha ) ) ?
0x20 :
0x10 );
if( (tmp->iType == GL_TRIANGLES) if( (tmp->iType == GL_TRIANGLES)
&& (tmp->iFlags & 0x10) && (tmp->iFlags & 0x10)
&& (Global::pTerrainCompact->TerrainLoaded()) ) { && (Global::pTerrainCompact->TerrainLoaded()) ) {
@@ -1327,7 +1324,6 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
vertex.normal = glm::rotateX( vertex.normal, static_cast<float>( aRotate.x / 180 * M_PI ) ); vertex.normal = glm::rotateX( vertex.normal, static_cast<float>( aRotate.x / 180 * M_PI ) );
vertex.normal = glm::rotateY( vertex.normal, static_cast<float>( aRotate.y / 180 * M_PI ) ); vertex.normal = glm::rotateY( vertex.normal, static_cast<float>( aRotate.y / 180 * M_PI ) );
vertex.position += glm::dvec3( pOrigin.x, pOrigin.y, pOrigin.z ); vertex.position += glm::dvec3( pOrigin.x, pOrigin.y, pOrigin.z );
tmp->pCenter += vertex.position;
// convert all data to gl_triangles to allow data merge for matching nodes // convert all data to gl_triangles to allow data merge for matching nodes
switch( tmp->iType ) { switch( tmp->iType ) {
case GL_TRIANGLES: { case GL_TRIANGLES: {
@@ -1370,6 +1366,10 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
auto const nv = importedvertices.size(); auto const nv = importedvertices.size();
tmp->Init(nv); // utworzenie tablicy wierzchołków tmp->Init(nv); // utworzenie tablicy wierzchołków
for( std::size_t i = 0; i < nv; ++i ) {
tmp->pCenter += importedvertices[ i ].position;
}
tmp->pCenter /= (nv > 0 ? nv : 1); tmp->pCenter /= (nv > 0 ? nv : 1);
r = 0; r = 0;
@@ -1411,7 +1411,6 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
vertex.position = glm::rotateY( vertex.position, aRotate.y / 180 * M_PI ); vertex.position = glm::rotateY( vertex.position, aRotate.y / 180 * M_PI );
vertex.position += glm::dvec3( pOrigin.x, pOrigin.y, pOrigin.z ); vertex.position += glm::dvec3( pOrigin.x, pOrigin.y, pOrigin.z );
tmp->pCenter += vertex.position;
// convert all data to gl_lines to allow data merge for matching nodes // convert all data to gl_lines to allow data merge for matching nodes
switch( tmp->iType ) { switch( tmp->iType ) {
case GL_LINES: { case GL_LINES: {
@@ -1460,10 +1459,11 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
auto const nv = importedvertices.size(); auto const nv = importedvertices.size();
tmp->Points = new glm::dvec3[ nv ]; tmp->Points = new glm::dvec3[ nv ];
tmp->iNumPts = nv; tmp->iNumPts = nv;
tmp->pCenter /= ( nv > 0 ? nv : 1 );
for( std::size_t i = 0; i < nv; ++i ) { for( std::size_t i = 0; i < nv; ++i ) {
tmp->Points[ i ] = importedvertices[ i ].position; tmp->Points[ i ] = importedvertices[ i ].position;
tmp->pCenter += importedvertices[ i ].position;
} }
tmp->pCenter /= ( nv > 0 ? nv : 1 );
break; break;
} }
} }

View File

@@ -149,7 +149,6 @@ public:
Diffuse{ 1.0f, 1.0f, 1.0f }, Diffuse{ 1.0f, 1.0f, 1.0f },
Specular{ 1.0f, 1.0f, 1.0f }; // oświetlenie Specular{ 1.0f, 1.0f, 1.0f }; // oświetlenie
double fLineThickness; // McZapkie-120702: grubosc linii double fLineThickness; // McZapkie-120702: grubosc linii
bool PROBLEND;
bool bVisible; bool bVisible;
TGroundNode(); TGroundNode();
@@ -283,7 +282,6 @@ class TGround
event_map m_eventmap; event_map m_eventmap;
TNames<TGroundNode *> m_trackmap; TNames<TGroundNode *> m_trackmap;
light_array m_lights; // collection of dynamic light sources present in the scene light_array m_lights; // collection of dynamic light sources present in the scene
bool PROBLEND;
private: // metody prywatne private: // metody prywatne
bool EventConditon(TEvent *e); bool EventConditon(TEvent *e);

View File

@@ -42,69 +42,6 @@ std::string *TSubModel::pasText;
// 0x3F3F003F - wszystkie wymienne tekstury używane w danym cyklu // 0x3F3F003F - wszystkie wymienne tekstury używane w danym cyklu
// Ale w TModel3d okerśla przezroczystość tekstur wymiennych! // Ale w TModel3d okerśla przezroczystość tekstur wymiennych!
TSubModel::TSubModel()
{
::SecureZeroMemory(this, sizeof(TSubModel)); // istotne przy zapisywaniu wersji binarnej
FirstInit();
};
void TSubModel::FirstInit()
{
eType = TP_ROTATOR;
/*
Vertices = NULL;
uiDisplayList = 0;
*/
iNumVerts = -1; // do sprawdzenia
/*
iVboPtr = -1;
*/
fLight = -1.0; //świetcenie wyłączone
v_RotateAxis = float3(0, 0, 0);
v_TransVector = float3(0, 0, 0);
f_Angle = 0;
b_Anim = at_None;
b_aAnim = at_None;
fVisible = 0.0; // zawsze widoczne
iVisible = 1;
fMatrix = NULL; // to samo co iMatrix=0;
Next = NULL;
Child = NULL;
TextureID = 0;
// TexAlpha=false;
iFlags = 0x0200; // bit 9=1: submodel został utworzony a nie ustawiony na
// wczytany plik
// TexHash=false;
// Hits=NULL;
// CollisionPts=NULL;
// CollisionPtsCount=0;
Opacity = 0.0f; // przy wczytywaniu modeli było dzielone przez 100...
bWire = false;
fWireSize = 0;
fNearAttenStart = 40;
fNearAttenEnd = 80;
bUseNearAtten = false;
iFarAttenDecay = 0;
fFarDecayRadius = 100.0f;
fCosFalloffAngle = 0.5f; // 120°?
fCosHotspotAngle = 0.3f; // 145°?
fCosViewAngle = 0;
fSquareMaxDist = 10000 * 10000; // 10km
fSquareMinDist = 0;
iName = -1; // brak nazwy
iTexture = 0; // brak tekstury
// asName="";
// asTexture="";
pName = "";
pTexture = "";
f4Ambient[0] = f4Ambient[1] = f4Ambient[2] = f4Ambient[3] = 1.0; //{1,1,1,1};
f4Diffuse[0] = f4Diffuse[1] = f4Diffuse[2] = f4Diffuse[3] = 1.0; //{1,1,1,1};
f4Specular[0] = f4Specular[1] = f4Specular[2] = 0.0;
f4Specular[3] = 1.0; //{0,0,0,1};
f4Emision[0] = f4Emision[1] = f4Emision[2] = f4Emision[3] = 1.0;
smLetter = NULL; // używany tylko roboczo dla TP_TEXT, do przyspieszenia wyświetlania
};
TSubModel::~TSubModel() TSubModel::~TSubModel()
{ {
/* /*
@@ -141,9 +78,6 @@ void TSubModel::NameSet(std::string const &Name)
pName = Name; pName = Name;
}; };
// int TSubModel::SeekFaceNormal(DWORD *Masks, int f,DWORD dwMask,vector3
// *pt,GLVERTEX
// *Vertices)
int TSubModel::SeekFaceNormal(std::vector<unsigned int> const &Masks, int const Startface, unsigned int const Mask, glm::vec3 const &Position, vertex_array const &Vertices) int TSubModel::SeekFaceNormal(std::vector<unsigned int> const &Masks, int const Startface, unsigned int const Mask, glm::vec3 const &Position, vertex_array const &Vertices)
{ // szukanie punktu stycznego do (pt), zwraca numer wierzchołka, a nie trójkąta { // szukanie punktu stycznego do (pt), zwraca numer wierzchołka, a nie trójkąta
int facecount = iNumVerts / 3; // bo maska powierzchni jest jedna na trójkąt int facecount = iNumVerts / 3; // bo maska powierzchni jest jedna na trójkąt
@@ -518,11 +452,14 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
std::vector<glm::vec3> facenormals; std::vector<glm::vec3> facenormals;
for( int i = 0; i < facecount; ++i ) { for( int i = 0; i < facecount; ++i ) {
// pętla po trójkątach - będzie szybciej, jak wstępnie przeliczymy normalne trójkątów // pętla po trójkątach - będzie szybciej, jak wstępnie przeliczymy normalne trójkątów
auto facenormal =
glm::cross(
Vertices[ i * 3 ].position - Vertices[ i * 3 + 1 ].position,
Vertices[ i * 3 ].position - Vertices[ i * 3 + 2 ].position );
facenormals.emplace_back( facenormals.emplace_back(
glm::normalize( glm::length( facenormal ) > 0.0f ?
glm::cross( glm::normalize( facenormal ) :
Vertices[ i * 3 ].position - Vertices[ i * 3 + 1 ].position, glm::vec3() );
Vertices[ i * 3 ].position - Vertices[ i * 3 + 2 ].position ) ) );
} }
glm::vec3 vertexnormal; // roboczy wektor normalny glm::vec3 vertexnormal; // roboczy wektor normalny
for (int vertexidx = 0; vertexidx < iNumVerts; ++vertexidx) { for (int vertexidx = 0; vertexidx < iNumVerts; ++vertexidx) {
@@ -544,7 +481,10 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
adjacenvertextidx = SeekFaceNormal(sg, adjacenvertextidx / 3 + 1, sg[faceidx], Vertices[vertexidx].position, Vertices); adjacenvertextidx = SeekFaceNormal(sg, adjacenvertextidx / 3 + 1, sg[faceidx], Vertices[vertexidx].position, Vertices);
} }
// Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane przez transformy, aby normalne po przeskalowaniu były jednostkowe // Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane przez transformy, aby normalne po przeskalowaniu były jednostkowe
Vertices[vertexidx].normal = glm::normalize(vertexnormal); // przepisanie do wierzchołka trójkąta Vertices[ vertexidx ].normal = (
glm::length( vertexnormal ) > 0.0f ?
glm::normalize( vertexnormal ) :
glm::vec3() ); // przepisanie do wierzchołka trójkąta
} }
} }
/* /*
@@ -755,7 +695,10 @@ void TSubModel::InitialRotate(bool doit)
if( eType != TP_STARS ) { if( eType != TP_STARS ) {
// gwiazdki mają kolory zamiast normalnych, to ich wtedy nie ruszamy // gwiazdki mają kolory zamiast normalnych, to ich wtedy nie ruszamy
for( auto &vertex : Vertices ) { for( auto &vertex : Vertices ) {
vertex.normal = glm::normalize( ( *mat ) * vertex.normal ); vertex.normal = (
glm::length( vertex.normal ) > 0.0f ?
glm::normalize( ( *mat ) * vertex.normal ) :
glm::vec3() );
} }
} }
} }
@@ -772,18 +715,18 @@ void TSubModel::InitialRotate(bool doit)
/* /*
for( auto &vertex : Vertices ) { for( auto &vertex : Vertices ) {
*/ */
for( int idx = 0; idx < iNumVerts; ++idx ) { for( auto &vertex : Vertices ) {
Vertices[idx].position.x = -Vertices[idx].position.x; // zmiana znaku X vertex.position.x = -vertex.position.x; // zmiana znaku X
swapcopy = Vertices[idx].position.y; // zamiana Y i Z swapcopy = vertex.position.y; // zamiana Y i Z
Vertices[idx].position.y = Vertices[idx].position.z; vertex.position.y = vertex.position.z;
Vertices[idx].position.z = swapcopy; vertex.position.z = swapcopy;
// wektory normalne również trzeba przekształcić, bo się źle oświetlają // wektory normalne również trzeba przekształcić, bo się źle oświetlają
if( eType != TP_STARS ) { if( eType != TP_STARS ) {
// gwiazdki mają kolory zamiast normalnych, to // ich wtedy nie ruszamy // gwiazdki mają kolory zamiast normalnych, to // ich wtedy nie ruszamy
Vertices[idx].normal.x = -Vertices[idx].normal.x; // zmiana znaku X vertex.normal.x = -vertex.normal.x; // zmiana znaku X
swapcopy = Vertices[idx].normal.y; // zamiana Y i Z swapcopy = vertex.normal.y; // zamiana Y i Z
Vertices[idx].normal.y = Vertices[idx].normal.z; vertex.normal.y = vertex.normal.z;
Vertices[idx].normal.z = swapcopy; vertex.normal.z = swapcopy;
} }
} }
// } // }
@@ -1050,30 +993,34 @@ void TSubModel::RaAnimation(TAnimType a)
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/*
void TSubModel::RaArrayFill(basic_vertex *Vert) void TSubModel::serialize_geometry( std::ostream &Output ) {
{ // wypełnianie tablic VBO
if (Child) if( Child ) {
Child->RaArrayFill(Vert); Child->serialize_geometry( Output );
if( ( eType < TP_ROTATOR ) || ( eType == TP_STARS ) ) }
for( int i = 0; i < iNumVerts; ++i ) { if( m_geometry != NULL ) {
Vert[ iVboPtr + i ].position = Vertices[ i ].position; for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
Vert[ iVboPtr + i ].normal = Vertices[ i ].normal; vertex.serialize( Output );
Vert[ iVboPtr + i ].texture = Vertices[ i ].texture;
} }
else if( eType == TP_FREESPOTLIGHT ) }
Vert[ iVboPtr ].position = glm::vec3(); if( Next ) {
if (Next) Next->serialize_geometry( Output );
Next->RaArrayFill(Vert); }
}; };
*/
void void
TSubModel::create_geometry( geometrybank_handle const &Bank ) { TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &Bank ) {
// data offset is used to determine data offset of each submodel into single shared geometry bank
// (the offsets are part of legacy system which we now need to work around for backward compatibility)
if( Child ) if( Child )
Child->create_geometry( Bank ); Child->create_geometry( Dataoffset, Bank );
if( false == Vertices.empty() ) { if( false == Vertices.empty() ) {
tVboPtr = static_cast<int>( Dataoffset );
Dataoffset += Vertices.size();
// conveniently all relevant custom node types use GL_POINTS, or we'd have to determine the type on individual basis // conveniently all relevant custom node types use GL_POINTS, or we'd have to determine the type on individual basis
auto type = ( auto type = (
eType < TP_ROTATOR ? eType < TP_ROTATOR ?
@@ -1083,7 +1030,7 @@ TSubModel::create_geometry( geometrybank_handle const &Bank ) {
} }
if( Next ) if( Next )
Next->create_geometry( Bank ); Next->create_geometry( Dataoffset, Bank );
} }
// NOTE: leftover from static distance factor adjustment. // NOTE: leftover from static distance factor adjustment.
@@ -1140,25 +1087,34 @@ void TSubModel::ParentMatrix(float4x4 *m)
// nie obrócono jeszcze // nie obrócono jeszcze
}; };
float TSubModel::MaxY( float4x4 const &m ) // obliczenie maksymalnej wysokości, na początek ślizgu w pantografie
{ // obliczenie maksymalnej wysokości, na początek ślizgu w pantografie float TSubModel::MaxY( float4x4 const &m ) {
if( eType != 4 ) { // tylko dla trójkątów liczymy
// tylko dla trójkątów liczymy if( eType != 4 ) { return 0; }
return 0;
}
if( m_geometry == NULL ) {
return 0;
}
auto maxy { 0.0f }; auto maxy { 0.0f };
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) { // binary and text models invoke this function at different stages, either after or before geometry data was sent to the geometry manager
if( m_geometry != NULL ) {
maxy = std::max( for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
maxy, maxy = std::max(
m[ 0 ][ 1 ] * vertex.position.x maxy,
+ m[ 1 ][ 1 ] * vertex.position.y m[ 0 ][ 1 ] * vertex.position.x
+ m[ 2 ][ 1 ] * vertex.position.z + m[ 1 ][ 1 ] * vertex.position.y
+ m[ 3 ][ 1 ] ); + m[ 2 ][ 1 ] * vertex.position.z
+ m[ 3 ][ 1 ] );
}
}
else if( false == Vertices.empty() ) {
for( auto const &vertex : Vertices ) {
maxy = std::max(
maxy,
m[ 0 ][ 1 ] * vertex.position.x
+ m[ 1 ][ 1 ] * vertex.position.y
+ m[ 2 ][ 1 ] * vertex.position.z
+ m[ 3 ][ 1 ] );
}
} }
return maxy; return maxy;
@@ -1316,10 +1272,10 @@ void TSubModel::serialize(std::ostream &s,
sn_utils::ls_int32(s, iFlags); sn_utils::ls_int32(s, iFlags);
sn_utils::ls_int32(s, (int32_t)get_container_pos(transforms, *fMatrix)); sn_utils::ls_int32(s, (int32_t)get_container_pos(transforms, *fMatrix));
/*
sn_utils::ls_int32(s, iNumVerts); sn_utils::ls_int32(s, iNumVerts);
sn_utils::ls_int32(s, (int)iVboPtr); sn_utils::ls_int32(s, tVboPtr);
*/
if (TextureID <= 0) if (TextureID <= 0)
sn_utils::ls_int32(s, TextureID); sn_utils::ls_int32(s, TextureID);
else else
@@ -1358,9 +1314,6 @@ void TSubModel::serialize(std::ostream &s,
void TModel3d::SaveToBinFile(std::string const &FileName) void TModel3d::SaveToBinFile(std::string const &FileName)
{ {
// TODO: re-implement!
return;
WriteLog("saving e3d model.."); WriteLog("saving e3d model..");
//m7todo: można by zoptymalizować robiąc unordered_map //m7todo: można by zoptymalizować robiąc unordered_map
@@ -1396,20 +1349,11 @@ void TModel3d::SaveToBinFile(std::string const &FileName)
sn_utils::ls_uint32(s, 8 + (uint32_t)transforms.size() * 64); sn_utils::ls_uint32(s, 8 + (uint32_t)transforms.size() * 64);
for (size_t i = 0; i < transforms.size(); i++) for (size_t i = 0; i < transforms.size(); i++)
transforms[i].serialize_float32(s); transforms[i].serialize_float32(s);
/*
MakeArray(iNumVerts); sn_utils::ls_uint32(s, MAKE_ID4('V', 'N', 'T', '0'));
#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); sn_utils::ls_uint32(s, 8 + iNumVerts * 32);
/* Root->serialize_geometry( s );
for (size_t i = 0; i < (size_t)iNumVerts; i++)
m_pVNT[i].serialize(s);
*/
if (textures.size()) if (textures.size())
{ {
sn_utils::ls_uint32(s, MAKE_ID4('T', 'E', 'X', '0')); sn_utils::ls_uint32(s, MAKE_ID4('T', 'E', 'X', '0'));
@@ -1555,6 +1499,7 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
for( auto const &submodeloffset : submodeloffsets ) { for( auto const &submodeloffset : submodeloffsets ) {
auto &submodel = Root[ submodeloffset.second ]; auto &submodel = Root[ submodeloffset.second ];
vertex_array vertices; vertices.resize( submodel.iNumVerts ); vertex_array vertices; vertices.resize( submodel.iNumVerts );
iNumVerts += submodel.iNumVerts;
for( auto &vertex : vertices ) { for( auto &vertex : vertices ) {
vertex.deserialize( s ); vertex.deserialize( s );
} }
@@ -1669,12 +1614,13 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
if (pTexture.find_last_of("/\\") == std::string::npos) if (pTexture.find_last_of("/\\") == std::string::npos)
pTexture.insert(0, Global::asCurrentTexturePath); pTexture.insert(0, Global::asCurrentTexturePath);
TextureID = GfxRenderer.GetTextureId(pTexture, szTexturePath); TextureID = GfxRenderer.GetTextureId(pTexture, szTexturePath);
/* if( ( iFlags & 0x30 ) == 0 ) {
iFlags |= // texture-alpha based fallback if for some reason we don't have opacity flag set yet
( GfxRenderer.Texture( TextureID ).has_alpha ? iFlags |=
0x20 : ( GfxRenderer.Texture( TextureID ).has_alpha ?
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta 0x20 :
*/ 0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
}
} }
else else
TextureID = iTexture; TextureID = iTexture;
@@ -1688,10 +1634,10 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
iFlags |= 0x20; iFlags |= 0x20;
} }
// intercept and fix hotspot values if specified in degrees and not directly // intercept and fix hotspot values if specified in degrees and not directly
if( fCosFalloffAngle > 1.0 ) { if( fCosFalloffAngle > 1.0f ) {
fCosFalloffAngle = std::cos( DegToRad( 0.5f * fCosFalloffAngle ) ); fCosFalloffAngle = std::cos( DegToRad( 0.5f * fCosFalloffAngle ) );
} }
if( fCosHotspotAngle > 1.0 ) { if( fCosHotspotAngle > 1.0f ) {
fCosHotspotAngle = std::cos( DegToRad( 0.5f * fCosHotspotAngle ) ); fCosHotspotAngle = std::cos( DegToRad( 0.5f * fCosHotspotAngle ) );
} }
@@ -1784,17 +1730,17 @@ void TModel3d::Init()
Root->InitialRotate(true); // argumet określa, czy wykonać pierwotny obrót Root->InitialRotate(true); // argumet określa, czy wykonać pierwotny obrót
} }
iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu
if (false == asBinary.empty()) // jeśli jest podana nazwa
{
if (Global::iConvertModels) // i włączony zapis
SaveToBinFile( asBinary ); // utworzy tablicę (m_pVNT)
asBinary = ""; // zablokowanie powtórnego zapisu
}
if (iNumVerts) { if (iNumVerts) {
if( m_geometrybank == NULL ) { if( m_geometrybank == NULL ) {
m_geometrybank = GfxRenderer.Create_Bank(); m_geometrybank = GfxRenderer.Create_Bank();
} }
Root->create_geometry( m_geometrybank ); std::size_t dataoffset = 0;
Root->create_geometry( dataoffset, m_geometrybank );
}
if( ( Global::iConvertModels > 0 )
&& ( false == asBinary.empty() ) ) {
SaveToBinFile( asBinary );
asBinary = ""; // zablokowanie powtórnego zapisu
} }
} }
}; };

110
Model3d.h
View File

@@ -7,8 +7,7 @@ obtain one at
http://mozilla.org/MPL/2.0/. http://mozilla.org/MPL/2.0/.
*/ */
#ifndef Model3dH #pragma once
#define Model3dH
#include "GL/glew.h" #include "GL/glew.h"
#include "Parser.h" #include "Parser.h"
@@ -51,8 +50,6 @@ enum TAnimType // rodzaj animacji
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
}; };
class TModel3d;
class TSubModel class TSubModel
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów { // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
//m7todo: zrobić normalną serializację //m7todo: zrobić normalną serializację
@@ -61,15 +58,16 @@ class TSubModel
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
private: private:
int iNext; int iNext{ NULL };
int iChild; int iChild{ NULL };
int eType; // Ra: modele binarne dają więcej możliwości niż mesh złożony z trójkątów int eType{ TP_ROTATOR }; // Ra: modele binarne dają więcej możliwości niż mesh złożony z trójkątów
int iName; // numer łańcucha z nazwą submodelu, albo -1 gdy anonimowy int iName{ -1 }; // numer łańcucha z nazwą submodelu, albo -1 gdy anonimowy
public: // chwilowo public: // chwilowo
TAnimType b_Anim; TAnimType b_Anim{ at_None };
private: private:
int iFlags; // flagi informacyjne: int iFlags{ 0x0200 }; // bit 9=1: submodel został utworzony a nie ustawiony na wczytany plik
// flagi informacyjne:
// bit 0: =1 faza rysowania zależy od wymiennej tekstury 0 // bit 0: =1 faza rysowania zależy od wymiennej tekstury 0
// bit 1: =1 faza rysowania zależy od wymiennej tekstury 1 // bit 1: =1 faza rysowania zależy od wymiennej tekstury 1
// bit 2: =1 faza rysowania zależy od wymiennej tekstury 2 // bit 2: =1 faza rysowania zależy od wymiennej tekstury 2
@@ -84,63 +82,62 @@ private:
// bit 15: =1 wymagane przechowanie macierzy (transform niejedynkowy) // bit 15: =1 wymagane przechowanie macierzy (transform niejedynkowy)
union union
{ // transform, nie każdy submodel musi mieć { // transform, nie każdy submodel musi mieć
float4x4 *fMatrix; // pojedyncza precyzja wystarcza float4x4 *fMatrix = nullptr; // pojedyncza precyzja wystarcza
int iMatrix; // w pliku binarnym jest numer matrycy int iMatrix; // w pliku binarnym jest numer matrycy
}; };
int iNumVerts; // ilość wierzchołków (1 dla FreeSpotLight) int iNumVerts{ -1 }; // ilość wierzchołków (1 dla FreeSpotLight)
int tVboPtr; // początek na liście wierzchołków albo indeksów int tVboPtr; // początek na liście wierzchołków albo indeksów
int iTexture; // numer nazwy tekstury, -1 wymienna, 0 brak int iTexture{ 0 }; // numer nazwy tekstury, -1 wymienna, 0 brak
float fVisible; // próg jasności światła do załączenia submodelu float fVisible{ 0.0f }; // próg jasności światła do załączenia submodelu
float fLight; // próg jasności światła do zadziałania selfillum float fLight{ -1.0f }; // próg jasności światła do zadziałania selfillum
glm::vec4 glm::vec4
f4Ambient, f4Ambient{ 1.0f,1.0f,1.0f,1.0f },
f4Diffuse, f4Diffuse{ 1.0f,1.0f,1.0f,1.0f },
f4Specular, f4Specular{ 0.0f,0.0f,0.0f,1.0f },
f4Emision; f4Emision{ 1.0f,1.0f,1.0f,1.0f };
float fWireSize; // nie używane, ale wczytywane float fWireSize{ 0.0f }; // nie używane, ale wczytywane
float fSquareMaxDist; float fSquareMaxDist{ 10000.0f * 10000.0f };
float fSquareMinDist; float fSquareMinDist{ 0.0f };
// McZapkie-050702: parametry dla swiatla: // McZapkie-050702: parametry dla swiatla:
float fNearAttenStart; float fNearAttenStart{ 40.0f };
float fNearAttenEnd; float fNearAttenEnd{ 80.0f };
bool bUseNearAtten; // te 3 zmienne okreslaja rysowanie aureoli wokol zrodla swiatla bool bUseNearAtten{ false }; // te 3 zmienne okreslaja rysowanie aureoli wokol zrodla swiatla
int iFarAttenDecay; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R) int iFarAttenDecay{ 0 }; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R)
float fFarDecayRadius; // normalizacja j.w. float fFarDecayRadius{ 100.0f }; // normalizacja j.w.
float fCosFalloffAngle; // cosinus kąta stożka pod którym widać światło float fCosFalloffAngle{ 0.5f }; // cosinus kąta stożka pod którym widać światło
float fCosHotspotAngle; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła float fCosHotspotAngle{ 0.3f }; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
float fCosViewAngle; // cos kata pod jakim sie teraz patrzy float fCosViewAngle{ 0.0f }; // cos kata pod jakim sie teraz patrzy
TSubModel *Next; TSubModel *Next{ nullptr };
TSubModel *Child; TSubModel *Child{ nullptr };
/* /*
intptr_t iVboPtr; intptr_t iVboPtr;
*/ */
geometry_handle m_geometry; // geometry of the submodel geometry_handle m_geometry{ NULL, NULL }; // geometry of the submodel
texture_handle TextureID; // numer tekstury, -1 wymienna, 0 brak texture_handle TextureID{ NULL }; // numer tekstury, -1 wymienna, 0 brak
bool bWire; // nie używane, ale wczytywane bool bWire{ false }; // nie używane, ale wczytywane
/* /*
GLuint uiDisplayList; // roboczy numer listy wyświetlania GLuint uiDisplayList; // roboczy numer listy wyświetlania
*/ */
float Opacity; // nie używane, ale wczytywane //m7todo: wywalić to float Opacity{ 1.0f };
float f_Angle; float f_Angle{ 0.0f };
float3 v_RotateAxis; float3 v_RotateAxis{ 0.0f, 0.0f, 0.0f };
float3 v_Angles; float3 v_Angles { 0.0f, 0.0f, 0.0f };
public: // chwilowo public: // chwilowo
float3 v_TransVector; float3 v_TransVector{ 0.0f, 0.0f, 0.0f };
/* /*
basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
*/ */
vertex_array Vertices; vertex_array Vertices;
size_t iAnimOwner; // roboczy numer egzemplarza, który ustawił animację size_t iAnimOwner{ NULL }; // roboczy numer egzemplarza, który ustawił animację
TAnimType b_aAnim; // kody animacji oddzielnie, bo zerowane TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane
public: public:
float4x4 *mAnimMatrix; // macierz do animacji kwaternionowych (należy do AnimContainer) float4x4 *mAnimMatrix{ nullptr }; // macierz do animacji kwaternionowych (należy do AnimContainer)
public: public:
TSubModel ** TSubModel **smLetter{ nullptr }; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
smLetter; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D) TSubModel *Parent{ nullptr }; // nadrzędny, np. do wymnażania macierzy
TSubModel *Parent; // nadrzędny, np. do wymnażania macierzy int iVisible{ 1 }; // roboczy stan widoczności
int iVisible; // roboczy stan widoczności
std::string pTexture; // robocza nazwa tekstury do zapisania w pliku binarnym std::string pTexture; // robocza nazwa tekstury do zapisania w pliku binarnym
std::string pName; // robocza nazwa std::string pName; // robocza nazwa
private: private:
@@ -154,9 +151,7 @@ public:
static double fSquareDist; static double fSquareDist;
static TModel3d *pRoot; static TModel3d *pRoot;
static std::string *pasText; // tekst dla wyświetlacza (!!!! do przemyślenia) static std::string *pasText; // tekst dla wyświetlacza (!!!! do przemyślenia)
TSubModel();
~TSubModel(); ~TSubModel();
void FirstInit();
int Load(cParser &Parser, TModel3d *Model, /*int Pos,*/ bool dynamic); int Load(cParser &Parser, TModel3d *Model, /*int Pos,*/ bool dynamic);
void ChildAdd(TSubModel *SubModel); void ChildAdd(TSubModel *SubModel);
void NextAdd(TSubModel *SubModel); void NextAdd(TSubModel *SubModel);
@@ -176,10 +171,8 @@ public:
TSubModel * GetFromName(char const *search, bool i = true); TSubModel * GetFromName(char const *search, bool i = true);
inline float4x4 * GetMatrix() { return fMatrix; }; inline float4x4 * GetMatrix() { return fMatrix; };
inline void Hide() { iVisible = 0; }; inline void Hide() { iVisible = 0; };
/*
void RaArrayFill(basic_vertex *Vert); void create_geometry( std::size_t &Dataoffset, geometrybank_handle const &Bank );
*/
void create_geometry( geometrybank_handle const &Bank );
int FlagsCheck(); int FlagsCheck();
void WillBeAnimated() void WillBeAnimated()
{ {
@@ -187,9 +180,6 @@ public:
iFlags |= 0x4000; iFlags |= 0x4000;
}; };
void InitialRotate(bool doit); void InitialRotate(bool doit);
#ifdef EU07_USE_OLD_DRAW_CODE
void DisplayLists();
#endif
void BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t, std::vector<std::string> *n, bool dynamic); void BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t, std::vector<std::string> *n, bool dynamic);
void ReplacableSet(texture_handle const *r, int a) void ReplacableSet(texture_handle const *r, int a)
{ {
@@ -219,11 +209,13 @@ public:
void AdjustDist(); void AdjustDist();
void deserialize(std::istream&); void deserialize(std::istream&);
void TSubModel::serialize(std::ostream&, void serialize(std::ostream&,
std::vector<TSubModel*>&, std::vector<TSubModel*>&,
std::vector<std::string>&, std::vector<std::string>&,
std::vector<std::string>&, std::vector<std::string>&,
std::vector<float4x4>&); std::vector<float4x4>&);
void serialize_geometry( std::ostream &Output );
}; };
class TModel3d : public CMesh class TModel3d : public CMesh
@@ -259,11 +251,7 @@ public:
std::string NameGet() { return m_filename; }; std::string NameGet() { return m_filename; };
int TerrainCount(); int TerrainCount();
TSubModel * TerrainSquare(int n); TSubModel * TerrainSquare(int n);
#ifdef EU07_USE_OLD_RENDERCODE
void TerrainRenderVBO(int n);
#endif
void deserialize(std::istream &s, size_t size, bool dynamic); void deserialize(std::istream &s, size_t size, bool dynamic);
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif

View File

@@ -292,7 +292,7 @@ void TPythonScreenRenderer::updateTexture()
WriteLog(buff); WriteLog(buff);
#endif // _PY_INT_MORE_LOG #endif // _PY_INT_MORE_LOG
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, _textureId); GfxRenderer.Bind(_textureId);
// setup texture parameters // setup texture parameters
if( GLEW_VERSION_1_4 ) { if( GLEW_VERSION_1_4 ) {

View File

@@ -1651,15 +1651,13 @@ TWorld::Update_UI() {
case( GLFW_KEY_F8 ) : { case( GLFW_KEY_F8 ) : {
// gfx renderer data // gfx renderer data
uitextline1 = uitextline1 =
"Draw range x " + to_string( Global::fDistanceFactor, 1 ) "FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 )
+ "; FPS: " + to_string( Timer::GetFPS(), 2 ); + ", Draw range x " + to_string( Global::fDistanceFactor, 1 )
+ "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
+ ", FPS: " + to_string( Timer::GetFPS(), 2 );
if( Global::iSlowMotion ) { if( Global::iSlowMotion ) {
uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")"; uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
} }
uitextline1 +=
", sectors: " + std::to_string( GfxRenderer.m_drawcount )
+ "/" + std::to_string( Global::iSegmentsRendered )
+ "; FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 );
uitextline2 = uitextline2 =
std::string( "Rendering mode: " ) std::string( "Rendering mode: " )

View File

@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include "globals.h" #include "globals.h"
void void
basic_vertex::serialize( std::ostream &s ) { basic_vertex::serialize( std::ostream &s ) const {
sn_utils::ls_float32( s, position.x ); sn_utils::ls_float32( s, position.x );
sn_utils::ls_float32( s, position.y ); sn_utils::ls_float32( s, position.y );

View File

@@ -27,7 +27,7 @@ struct basic_vertex {
basic_vertex( glm::vec3 const&Position, glm::vec3 const &Normal, glm::vec2 const &Texture ) : basic_vertex( glm::vec3 const&Position, glm::vec3 const &Normal, glm::vec2 const &Texture ) :
position( Position ), normal( Normal ), texture( Texture ) position( Position ), normal( Normal ), texture( Texture )
{} {}
void serialize( std::ostream& ); void serialize( std::ostream& ) const;
void deserialize( std::istream& ); void deserialize( std::istream& );
}; };
@@ -111,10 +111,12 @@ protected:
struct geometry_chunk { struct geometry_chunk {
unsigned int type; // kind of geometry used by the chunk unsigned int type; // kind of geometry used by the chunk
vertex_array vertices; // geometry data vertex_array vertices; // geometry data
// NOTE: constructor doesn't copy provided vertex data, but moves it
geometry_chunk( vertex_array &Vertices, unsigned int const Type ) : geometry_chunk( vertex_array &Vertices, unsigned int const Type ) :
vertices( Vertices ), type( Type ) type( Type )
{} {
vertices.swap( Vertices );
}
}; };
typedef std::vector<geometry_chunk> geometrychunk_sequence; typedef std::vector<geometry_chunk> geometrychunk_sequence;

View File

@@ -368,7 +368,14 @@ opengl_renderer::Render( TGround *Ground ) {
++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji) ++TGroundRect::iFrameNumber; // zwięszenie licznika ramek (do usuwniania nadanimacji)
Update_Lights( Ground->m_lights ); Update_Lights( Ground->m_lights );
/*
m_drawqueue.clear();
// rednerowanie globalnych (nie za często?)
for( TGroundNode *node = Ground->srGlobal.nRenderHidden; node; node = node->nNext3 ) {
node->RenderHidden();
}
glm::vec3 const cameraposition( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z ); glm::vec3 const cameraposition( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 ); int const camerax = static_cast<int>( std::floor( cameraposition.x / 1000.0f ) + iNumRects / 2 );
int const cameraz = static_cast<int>( std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2 ); int const cameraz = static_cast<int>( std::floor( cameraposition.z / 1000.0f ) + iNumRects / 2 );
@@ -380,89 +387,40 @@ opengl_renderer::Render( TGround *Ground ) {
for( int row = originz; row <= originz + segmentcount; ++row ) { for( int row = originz; row <= originz + segmentcount; ++row ) {
auto *cell = &Ground->Rects[ column ][ row ]; auto *cell = &Ground->Rects[ column ][ row ];
for( int subcellcolumn = 0; subcellcolumn < iNumSubRects; ++subcellcolumn ) {
for( int subcellrow = 0; subcellrow < iNumSubRects; ++subcellrow ) {
auto subcell = cell->FastGetSubRect( subcellcolumn, subcellrow );
if( subcell == nullptr ) { continue; }
// renderowanie obiektów aktywnych a niewidocznych
for( auto node = subcell->nRenderHidden; node; node = node->nNext3 ) {
node->RenderHidden();
}
// jeszcze dźwięki pojazdów by się przydały, również niewidocznych
subcell->RenderSounds();
}
}
if( m_camera.visible( cell->m_area ) ) { if( m_camera.visible( cell->m_area ) ) {
Render( cell ); Render( cell );
} }
} }
} }
*/
Ground->CameraDirection.x = std::sin( Global::pCameraRotation ); // wektor kierunkowy // draw queue was filled while rendering content of ground cells. now sort the nodes based on their distance to viewer...
Ground->CameraDirection.z = std::cos( Global::pCameraRotation ); std::sort(
TGroundNode *node; std::begin( m_drawqueue ),
// rednerowanie globalnych (nie za często?) std::end( m_drawqueue ),
for( node = Ground->srGlobal.nRenderHidden; node; node = node->nNext3 ) { []( distancesubcell_pair const &Left, distancesubcell_pair const &Right ) {
node->RenderHidden(); return ( Left.first ) < ( Right.first ); } );
// ...then render the opaque content of the visible subcells.
for( auto subcellpair : m_drawqueue ) {
Render( subcellpair.second );
} }
// renderowanie czołgowe dla obiektów aktywnych a niewidocznych // now hand the control over to the renderer of translucent parts, it'll do the rest
int n = 2 * iNumSubRects; //(2*==2km) promień wyświetlanej mapy w sektorach
int c = Ground->GetColFromX( Global::pCameraPosition.x );
int r = Ground->GetRowFromZ( Global::pCameraPosition.z );
TSubRect *tmp;
int i, j, k;
for( j = r - n; j <= r + n; ++j ) {
for( i = c - n; i <= c + n; ++i ) {
if( ( tmp = Ground->FastGetSubRect( i, j ) ) != nullptr ) {
// oznaczanie aktywnych sektorów
tmp->LoadNodes();
for( node = tmp->nRenderHidden; node; node = node->nNext3 ) {
node->RenderHidden();
}
// jeszcze dźwięki pojazdów by się przydały, również niewidocznych
tmp->RenderSounds();
}
}
}
// renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
// pre-calculate camera view span
double const fieldofviewcosine =
std::cos(
std::max(
// vertical...
Global::FieldOfView / Global::ZoomFactor,
// ...or horizontal, whichever is bigger
Global::FieldOfView / Global::ZoomFactor
* std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ) ) );
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
i = SectorOrder[ k ].x; // na starcie oba >=0
j = SectorOrder[ k ].y;
do {
// pierwszy przebieg: j<=0, i>=0; drugi: j>=0, i<=0; trzeci: j<=0, i<=0 czwarty: j>=0, i>=0;
if( j <= 0 )
i = -i;
j = -j; // i oraz j musi być zmienione wcześniej, żeby continue działało
direction = Math3D::vector3( i, 0, j ); // wektor od kamery do danego sektora
if( Math3D::LengthSquared3( direction ) > 5 ) // te blisko są zawsze wyświetlane
{
direction = Math3D::SafeNormalize( direction ); // normalizacja
if( Ground->CameraDirection.x * direction.x + Ground->CameraDirection.z * direction.z < 0.5 )
continue; // pomijanie sektorów poza kątem patrzenia
}
// kwadrat kilometrowy nie zawsze, bo szkoda FPS
Render( &Ground->Rects[ ( i + c ) / iNumSubRects ][ ( j + r ) / iNumSubRects ] );
if( ( tmp = Ground->FastGetSubRect( i + c, j + r ) ) != nullptr ) {
if( tmp->iNodeCount ) {
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
m_drawqueue.emplace_back( tmp );
}
}
} while( ( i < 0 ) || ( j < 0 ) ); // są 4 przypadki, oprócz i=j=0
}
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 ); return Render_Alpha( Ground );
} }
// TODO: unify ground render code, until then old version is in place
bool bool
opengl_renderer::Render( TGroundRect *Groundcell ) { opengl_renderer::Render( TGroundRect *Groundcell ) {
@@ -484,6 +442,19 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
} }
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
result = true; result = true;
// add the subcells of the cell to the draw queue
if( Groundcell->pSubRects != nullptr ) {
for( std::size_t subcellindex = 0; subcellindex < iNumSubRects * iNumSubRects; ++subcellindex ) {
auto subcell = Groundcell->pSubRects + subcellindex;
if( subcell->iNodeCount ) {
// o ile są jakieś obiekty, bo po co puste sektory przelatywać
m_drawqueue.emplace_back(
( Global::pCameraPosition - glm::dvec3( subcell->m_area.center ) ).LengthSquared(),
subcell );
}
}
}
} }
return result; return result;
} }
@@ -491,6 +462,9 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
bool bool
opengl_renderer::Render( TSubRect *Groundsubcell ) { opengl_renderer::Render( TSubRect *Groundsubcell ) {
// oznaczanie aktywnych sektorów
Groundsubcell->LoadNodes();
Groundsubcell->RaAnimate(); // przeliczenia animacji torów w sektorze Groundsubcell->RaAnimate(); // przeliczenia animacji torów w sektorze
TGroundNode *node; TGroundNode *node;
@@ -906,23 +880,23 @@ opengl_renderer::Render_Alpha( TGround *Ground ) {
TGroundNode *node; TGroundNode *node;
TSubRect *tmp; TSubRect *tmp;
// Ra: renderowanie progresywne - zależne od FPS oraz kierunku patrzenia // Ra: renderowanie progresywne - zależne od FPS oraz kierunku patrzenia
for( auto subcell = std::rbegin( m_drawqueue ); subcell != std::rend( m_drawqueue ); ++subcell ) { for( auto subcellpair = std::rbegin( m_drawqueue ); subcellpair != std::rend( m_drawqueue ); ++subcellpair ) {
// przezroczyste trójkąty w oddzielnym cyklu przed modelami // przezroczyste trójkąty w oddzielnym cyklu przed modelami
tmp = *subcell; tmp = subcellpair->second;
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) { for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
Render_Alpha( node ); Render_Alpha( node );
} }
} }
for( auto subcell = std::rbegin( m_drawqueue ); subcell != std::rend( m_drawqueue ); ++subcell ) for( auto subcellpair = std::rbegin( m_drawqueue ); subcellpair != std::rend( m_drawqueue ); ++subcellpair )
{ // renderowanie przezroczystych modeli oraz pojazdów { // renderowanie przezroczystych modeli oraz pojazdów
Render_Alpha( *subcell ); Render_Alpha( subcellpair->second );
} }
::glDisable( GL_LIGHTING ); // linie nie powinny świecić ::glDisable( GL_LIGHTING ); // linie nie powinny świecić
for( auto subcell = std::rbegin( m_drawqueue ); subcell != std::rend( m_drawqueue ); ++subcell ) { for( auto subcellpair = std::rbegin( m_drawqueue ); subcellpair != std::rend( m_drawqueue ); ++subcellpair ) {
// druty na końcu, żeby się nie robiły białe plamy na tle lasu // druty na końcu, żeby się nie robiły białe plamy na tle lasu
tmp = *subcell; tmp = subcellpair->second;
for( node = tmp->nRenderWires; node; node = node->nNext3 ) { for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
Render_Alpha( node ); Render_Alpha( node );
} }
@@ -947,25 +921,9 @@ opengl_renderer::Render_Alpha( TSubRect *Groundsubcell ) {
return true; return true;
} }
// NOTE: legacy render system switch
#define _PROBLEND
bool bool
opengl_renderer::Render_Alpha( TGroundNode *Node ) { opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// SPOSOB NA POZBYCIE SIE RAMKI DOOKOLA TEXTURY ALPHA DLA OBIEKTOW ZAGNIEZDZONYCH W SCN JAKO
// NODE
// W GROUND.H dajemy do klasy TGroundNode zmienna bool PROBLEND to samo robimy w klasie TGround
// nastepnie podczas wczytywania textury dla TRIANGLES w TGround::AddGroundNode
// sprawdzamy czy w nazwie jest @ i wg tego
// ustawiamy PROBLEND na true dla wlasnie wczytywanego trojkata (kazdy trojkat jest osobnym
// nodem)
// nastepnie podczas renderowania w bool TGroundNode::RenderAlpha()
// na poczatku ustawiamy standardowe GL_GREATER = 0.04
// pozniej sprawdzamy czy jest wlaczony PROBLEND dla aktualnie renderowanego noda TRIANGLE,
// wlasciwie dla kazdego node'a
// i jezeli tak to odpowiedni GL_GREATER w przeciwnym wypadku standardowy 0.04
double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor ); double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) ) if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) { || ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
@@ -1029,14 +987,15 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
return false; return false;
} }
// setup // setup
// w zaleznosci od koloru swiatla auto const linewidth = clamp( 100.0 * Node->fLineThickness / ( distancesquared + 1.0 ), 1.0, 10.0 );
::glColor4fv( ::glColor4fv(
glm::value_ptr( glm::value_ptr(
glm::vec4( glm::vec4(
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
std::min( std::min( 1.0, linewidth ) ) ) );
1.0, if( linewidth > 1.0 ) {
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) ); ::glLineWidth( static_cast<float>(linewidth) );
}
GfxRenderer.Bind( 0 ); GfxRenderer.Bind( 0 );
@@ -1048,6 +1007,10 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
m_geometry.draw( Node->m_geometry ); m_geometry.draw( Node->m_geometry );
// post-render cleanup // post-render cleanup
if( linewidth > 1.0 ) {
::glLineWidth( 1.0f );
}
::glPopMatrix(); ::glPopMatrix();
return true; return true;
@@ -1059,13 +1022,6 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
return false; return false;
} }
// setup // 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 ) ); ::glColor3fv( glm::value_ptr( Node->Diffuse ) );
Bind( Node->TextureID ); Bind( Node->TextureID );
@@ -1080,13 +1036,6 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// post-render cleanup // post-render cleanup
::glPopMatrix(); ::glPopMatrix();
#ifdef _PROBLEND
if( ( Node->PROBLEND ) ) // sprawdza, czy w nazwie nie ma @ //Q: 13122011 - Szociu: 27012012
{
::glEnable( GL_BLEND );
::glAlphaFunc( GL_GREATER, 0.04f );
}
#endif
return true; return true;
} }

View File

@@ -182,6 +182,8 @@ private:
typedef std::vector<opengl_light> opengllight_array; typedef std::vector<opengl_light> opengllight_array;
typedef std::pair< double, TSubRect * > distancesubcell_pair;
// methods // methods
bool bool
Init_caps(); Init_caps();
@@ -226,7 +228,7 @@ private:
texture_handle m_moontexture { -1 }; texture_handle m_moontexture { -1 };
geometry_handle m_billboardgeometry { 0, 0 }; geometry_handle m_billboardgeometry { 0, 0 };
GLUquadricObj *m_quadric; // helper object for drawing debug mode scene elements 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 std::vector<distancesubcell_pair> m_drawqueue; // list of subcells to be drawn in current render pass
}; };

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 17 #define VERSION_MAJOR 17
#define VERSION_MINOR 613 #define VERSION_MINOR 617
#define VERSION_REVISION 0 #define VERSION_REVISION 0