16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 03:09:18 +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 "uilayer.h"
#define _PROBLEND 1
//---------------------------------------------------------------------------
extern "C"
@@ -1283,18 +1282,16 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
*parser >> 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->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)
&& (tmp->iFlags & 0x10)
&& (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::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;
// convert all data to gl_triangles to allow data merge for matching nodes
switch( tmp->iType ) {
case GL_TRIANGLES: {
@@ -1370,6 +1366,10 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
auto const nv = importedvertices.size();
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);
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::dvec3( pOrigin.x, pOrigin.y, pOrigin.z );
tmp->pCenter += vertex.position;
// convert all data to gl_lines to allow data merge for matching nodes
switch( tmp->iType ) {
case GL_LINES: {
@@ -1460,10 +1459,11 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
auto const nv = importedvertices.size();
tmp->Points = new glm::dvec3[ nv ];
tmp->iNumPts = nv;
tmp->pCenter /= ( nv > 0 ? nv : 1 );
for( std::size_t i = 0; i < nv; ++i ) {
tmp->Points[ i ] = importedvertices[ i ].position;
tmp->pCenter += importedvertices[ i ].position;
}
tmp->pCenter /= ( nv > 0 ? nv : 1 );
break;
}
}

View File

@@ -149,7 +149,6 @@ public:
Diffuse{ 1.0f, 1.0f, 1.0f },
Specular{ 1.0f, 1.0f, 1.0f }; // oświetlenie
double fLineThickness; // McZapkie-120702: grubosc linii
bool PROBLEND;
bool bVisible;
TGroundNode();
@@ -283,7 +282,6 @@ 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);

View File

@@ -42,69 +42,6 @@ std::string *TSubModel::pasText;
// 0x3F3F003F - wszystkie wymienne tekstury używane w danym cyklu
// 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()
{
/*
@@ -141,9 +78,6 @@ void TSubModel::NameSet(std::string const &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)
{ // 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
@@ -518,11 +452,14 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
std::vector<glm::vec3> facenormals;
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
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(
glm::normalize(
glm::cross(
Vertices[ i * 3 ].position - Vertices[ i * 3 + 1 ].position,
Vertices[ i * 3 ].position - Vertices[ i * 3 + 2 ].position ) ) );
glm::length( facenormal ) > 0.0f ?
glm::normalize( facenormal ) :
glm::vec3() );
}
glm::vec3 vertexnormal; // roboczy wektor normalny
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);
}
// 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 ) {
// gwiazdki mają kolory zamiast normalnych, to ich wtedy nie ruszamy
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( int idx = 0; idx < iNumVerts; ++idx ) {
Vertices[idx].position.x = -Vertices[idx].position.x; // zmiana znaku X
swapcopy = Vertices[idx].position.y; // zamiana Y i Z
Vertices[idx].position.y = Vertices[idx].position.z;
Vertices[idx].position.z = swapcopy;
for( auto &vertex : Vertices ) {
vertex.position.x = -vertex.position.x; // zmiana znaku X
swapcopy = vertex.position.y; // zamiana Y i Z
vertex.position.y = vertex.position.z;
vertex.position.z = swapcopy;
// wektory normalne również trzeba przekształcić, bo się źle oświetlają
if( eType != TP_STARS ) {
// gwiazdki mają kolory zamiast normalnych, to // ich wtedy nie ruszamy
Vertices[idx].normal.x = -Vertices[idx].normal.x; // zmiana znaku X
swapcopy = Vertices[idx].normal.y; // zamiana Y i Z
Vertices[idx].normal.y = Vertices[idx].normal.z;
Vertices[idx].normal.z = swapcopy;
vertex.normal.x = -vertex.normal.x; // zmiana znaku X
swapcopy = vertex.normal.y; // zamiana Y i Z
vertex.normal.y = vertex.normal.z;
vertex.normal.z = swapcopy;
}
}
// }
@@ -1050,30 +993,34 @@ void TSubModel::RaAnimation(TAnimType a)
};
//---------------------------------------------------------------------------
/*
void TSubModel::RaArrayFill(basic_vertex *Vert)
{ // wypełnianie tablic VBO
if (Child)
Child->RaArrayFill(Vert);
if( ( eType < TP_ROTATOR ) || ( eType == TP_STARS ) )
for( int i = 0; i < iNumVerts; ++i ) {
Vert[ iVboPtr + i ].position = Vertices[ i ].position;
Vert[ iVboPtr + i ].normal = Vertices[ i ].normal;
Vert[ iVboPtr + i ].texture = Vertices[ i ].texture;
void TSubModel::serialize_geometry( std::ostream &Output ) {
if( Child ) {
Child->serialize_geometry( Output );
}
if( m_geometry != NULL ) {
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
vertex.serialize( Output );
}
else if( eType == TP_FREESPOTLIGHT )
Vert[ iVboPtr ].position = glm::vec3();
if (Next)
Next->RaArrayFill(Vert);
}
if( Next ) {
Next->serialize_geometry( Output );
}
};
*/
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 )
Child->create_geometry( Bank );
Child->create_geometry( Dataoffset, Bank );
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
auto type = (
eType < TP_ROTATOR ?
@@ -1083,7 +1030,7 @@ TSubModel::create_geometry( geometrybank_handle const &Bank ) {
}
if( Next )
Next->create_geometry( Bank );
Next->create_geometry( Dataoffset, Bank );
}
// NOTE: leftover from static distance factor adjustment.
@@ -1140,25 +1087,34 @@ void TSubModel::ParentMatrix(float4x4 *m)
// nie obrócono jeszcze
};
float TSubModel::MaxY( float4x4 const &m )
{ // obliczenie maksymalnej wysokości, na początek ślizgu w pantografie
if( eType != 4 ) {
// tylko dla trójkątów liczymy
return 0;
}
if( m_geometry == NULL ) {
return 0;
}
// obliczenie maksymalnej wysokości, na początek ślizgu w pantografie
float TSubModel::MaxY( float4x4 const &m ) {
// tylko dla trójkątów liczymy
if( eType != 4 ) { return 0; }
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(
maxy,
m[ 0 ][ 1 ] * vertex.position.x
+ m[ 1 ][ 1 ] * vertex.position.y
+ m[ 2 ][ 1 ] * vertex.position.z
+ m[ 3 ][ 1 ] );
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
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 ] );
}
}
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;
@@ -1316,10 +1272,10 @@ void TSubModel::serialize(std::ostream &s,
sn_utils::ls_int32(s, iFlags);
sn_utils::ls_int32(s, (int32_t)get_container_pos(transforms, *fMatrix));
/*
sn_utils::ls_int32(s, iNumVerts);
sn_utils::ls_int32(s, (int)iVboPtr);
*/
sn_utils::ls_int32(s, tVboPtr);
if (TextureID <= 0)
sn_utils::ls_int32(s, TextureID);
else
@@ -1358,9 +1314,6 @@ void TSubModel::serialize(std::ostream &s,
void TModel3d::SaveToBinFile(std::string const &FileName)
{
// TODO: re-implement!
return;
WriteLog("saving e3d model..");
//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);
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, 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);
*/
Root->serialize_geometry( s );
if (textures.size())
{
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 ) {
auto &submodel = Root[ submodeloffset.second ];
vertex_array vertices; vertices.resize( submodel.iNumVerts );
iNumVerts += submodel.iNumVerts;
for( auto &vertex : vertices ) {
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)
pTexture.insert(0, Global::asCurrentTexturePath);
TextureID = GfxRenderer.GetTextureId(pTexture, szTexturePath);
/*
iFlags |=
( GfxRenderer.Texture( TextureID ).has_alpha ?
0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
*/
if( ( iFlags & 0x30 ) == 0 ) {
// texture-alpha based fallback if for some reason we don't have opacity flag set yet
iFlags |=
( GfxRenderer.Texture( TextureID ).has_alpha ?
0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
}
}
else
TextureID = iTexture;
@@ -1688,10 +1634,10 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
iFlags |= 0x20;
}
// 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 ) );
}
if( fCosHotspotAngle > 1.0 ) {
if( fCosHotspotAngle > 1.0f ) {
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
}
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( m_geometrybank == NULL ) {
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/.
*/
#ifndef Model3dH
#define Model3dH
#pragma once
#include "GL/glew.h"
#include "Parser.h"
@@ -51,8 +50,6 @@ enum TAnimType // rodzaj animacji
at_Undefined = 0x800000FF // animacja chwilowo nieokreślona
};
class TModel3d;
class TSubModel
{ // klasa submodelu - pojedyncza siatka, punkt świetlny albo grupa punktów
//m7todo: zrobić normalną serializację
@@ -61,15 +58,16 @@ class TSubModel
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
private:
int iNext;
int iChild;
int eType; // 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 iNext{ NULL };
int iChild{ NULL };
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{ -1 }; // numer łańcucha z nazwą submodelu, albo -1 gdy anonimowy
public: // chwilowo
TAnimType b_Anim;
TAnimType b_Anim{ at_None };
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 1: =1 faza rysowania zależy od wymiennej tekstury 1
// bit 2: =1 faza rysowania zależy od wymiennej tekstury 2
@@ -84,63 +82,62 @@ private:
// bit 15: =1 wymagane przechowanie macierzy (transform niejedynkowy)
union
{ // 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 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 iTexture; // numer nazwy tekstury, -1 wymienna, 0 brak
float fVisible; // próg jasności światła do załączenia submodelu
float fLight; // próg jasności światła do zadziałania selfillum
int iTexture{ 0 }; // numer nazwy tekstury, -1 wymienna, 0 brak
float fVisible{ 0.0f }; // próg jasności światła do załączenia submodelu
float fLight{ -1.0f }; // próg jasności światła do zadziałania selfillum
glm::vec4
f4Ambient,
f4Diffuse,
f4Specular,
f4Emision;
float fWireSize; // nie używane, ale wczytywane
float fSquareMaxDist;
float fSquareMinDist;
f4Ambient{ 1.0f,1.0f,1.0f,1.0f },
f4Diffuse{ 1.0f,1.0f,1.0f,1.0f },
f4Specular{ 0.0f,0.0f,0.0f,1.0f },
f4Emision{ 1.0f,1.0f,1.0f,1.0f };
float fWireSize{ 0.0f }; // nie używane, ale wczytywane
float fSquareMaxDist{ 10000.0f * 10000.0f };
float fSquareMinDist{ 0.0f };
// McZapkie-050702: parametry dla swiatla:
float fNearAttenStart;
float fNearAttenEnd;
bool bUseNearAtten; // 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)
float fFarDecayRadius; // normalizacja j.w.
float fCosFalloffAngle; // 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 fCosViewAngle; // cos kata pod jakim sie teraz patrzy
float fNearAttenStart{ 40.0f };
float fNearAttenEnd{ 80.0f };
bool bUseNearAtten{ false }; // te 3 zmienne okreslaja rysowanie aureoli wokol zrodla swiatla
int iFarAttenDecay{ 0 }; // ta zmienna okresla typ zaniku natezenia swiatla (0:brak, 1,2: potega 1/R)
float fFarDecayRadius{ 100.0f }; // normalizacja j.w.
float fCosFalloffAngle{ 0.5f }; // cosinus kąta stożka pod którym widać światło
float fCosHotspotAngle{ 0.3f }; // cosinus kąta stożka pod którym widać aureolę i zwiększone natężenie światła
float fCosViewAngle{ 0.0f }; // cos kata pod jakim sie teraz patrzy
TSubModel *Next;
TSubModel *Child;
TSubModel *Next{ nullptr };
TSubModel *Child{ nullptr };
/*
intptr_t iVboPtr;
*/
geometry_handle m_geometry; // geometry of the submodel
texture_handle TextureID; // numer tekstury, -1 wymienna, 0 brak
bool bWire; // nie używane, ale wczytywane
geometry_handle m_geometry{ NULL, NULL }; // geometry of the submodel
texture_handle TextureID{ NULL }; // numer tekstury, -1 wymienna, 0 brak
bool bWire{ false }; // nie używane, ale wczytywane
/*
GLuint uiDisplayList; // roboczy numer listy wyświetlania
*/
float Opacity; // nie używane, ale wczytywane //m7todo: wywalić to
float f_Angle;
float3 v_RotateAxis;
float3 v_Angles;
float Opacity{ 1.0f };
float f_Angle{ 0.0f };
float3 v_RotateAxis{ 0.0f, 0.0f, 0.0f };
float3 v_Angles { 0.0f, 0.0f, 0.0f };
public: // chwilowo
float3 v_TransVector;
float3 v_TransVector{ 0.0f, 0.0f, 0.0f };
/*
basic_vertex *Vertices; // roboczy wskaźnik - wczytanie T3D do VBO
*/
vertex_array Vertices;
size_t iAnimOwner; // roboczy numer egzemplarza, który ustawił animację
TAnimType b_aAnim; // kody animacji oddzielnie, bo zerowane
size_t iAnimOwner{ NULL }; // roboczy numer egzemplarza, który ustawił animację
TAnimType b_aAnim{ at_None }; // kody animacji oddzielnie, bo zerowane
public:
float4x4 *mAnimMatrix; // macierz do animacji kwaternionowych (należy do AnimContainer)
float4x4 *mAnimMatrix{ nullptr }; // macierz do animacji kwaternionowych (należy do AnimContainer)
public:
TSubModel **
smLetter; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
TSubModel *Parent; // nadrzędny, np. do wymnażania macierzy
int iVisible; // roboczy stan widoczności
TSubModel **smLetter{ nullptr }; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
TSubModel *Parent{ nullptr }; // nadrzędny, np. do wymnażania macierzy
int iVisible{ 1 }; // roboczy stan widoczności
std::string pTexture; // robocza nazwa tekstury do zapisania w pliku binarnym
std::string pName; // robocza nazwa
private:
@@ -154,9 +151,7 @@ public:
static double fSquareDist;
static TModel3d *pRoot;
static std::string *pasText; // tekst dla wyświetlacza (!!!! do przemyślenia)
TSubModel();
~TSubModel();
void FirstInit();
int Load(cParser &Parser, TModel3d *Model, /*int Pos,*/ bool dynamic);
void ChildAdd(TSubModel *SubModel);
void NextAdd(TSubModel *SubModel);
@@ -176,10 +171,8 @@ public:
TSubModel * GetFromName(char const *search, bool i = true);
inline float4x4 * GetMatrix() { return fMatrix; };
inline void Hide() { iVisible = 0; };
/*
void RaArrayFill(basic_vertex *Vert);
*/
void create_geometry( geometrybank_handle const &Bank );
void create_geometry( std::size_t &Dataoffset, geometrybank_handle const &Bank );
int FlagsCheck();
void WillBeAnimated()
{
@@ -187,9 +180,6 @@ public:
iFlags |= 0x4000;
};
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 ReplacableSet(texture_handle const *r, int a)
{
@@ -219,11 +209,13 @@ public:
void AdjustDist();
void deserialize(std::istream&);
void TSubModel::serialize(std::ostream&,
void serialize(std::ostream&,
std::vector<TSubModel*>&,
std::vector<std::string>&,
std::vector<std::string>&,
std::vector<float4x4>&);
void serialize_geometry( std::ostream &Output );
};
class TModel3d : public CMesh
@@ -259,11 +251,7 @@ public:
std::string NameGet() { return m_filename; };
int TerrainCount();
TSubModel * TerrainSquare(int n);
#ifdef EU07_USE_OLD_RENDERCODE
void TerrainRenderVBO(int n);
#endif
void deserialize(std::istream &s, size_t size, bool dynamic);
};
//---------------------------------------------------------------------------
#endif

View File

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

View File

@@ -1651,15 +1651,13 @@ 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 );
"FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 )
+ ", Draw range x " + to_string( Global::fDistanceFactor, 1 )
+ "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
+ ", FPS: " + to_string( Timer::GetFPS(), 2 );
if( 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 =
std::string( "Rendering mode: " )

View File

@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include "globals.h"
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.y );

View File

@@ -27,7 +27,7 @@ struct basic_vertex {
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 serialize( std::ostream& ) const;
void deserialize( std::istream& );
};
@@ -111,10 +111,12 @@ protected:
struct geometry_chunk {
unsigned int type; // kind of geometry used by the chunk
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 ) :
vertices( Vertices ), type( Type )
{}
type( Type )
{
vertices.swap( Vertices );
}
};
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)
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 );
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 );
@@ -380,89 +387,40 @@ opengl_renderer::Render( TGround *Ground ) {
for( int row = originz; row <= originz + segmentcount; ++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 ) ) {
Render( cell );
}
}
}
*/
Ground->CameraDirection.x = std::sin( Global::pCameraRotation ); // wektor kierunkowy
Ground->CameraDirection.z = std::cos( Global::pCameraRotation );
TGroundNode *node;
// rednerowanie globalnych (nie za często?)
for( node = Ground->srGlobal.nRenderHidden; node; node = node->nNext3 ) {
node->RenderHidden();
// draw queue was filled while rendering content of ground cells. now sort the nodes based on their distance to viewer...
std::sort(
std::begin( m_drawqueue ),
std::end( m_drawqueue ),
[]( distancesubcell_pair const &Left, distancesubcell_pair const &Right ) {
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
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
// now hand the control over to the renderer of translucent parts, it'll do the rest
return Render_Alpha( Ground );
}
// TODO: unify ground render code, until then old version is in place
bool
opengl_renderer::Render( TGroundRect *Groundcell ) {
@@ -484,6 +442,19 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
}
Groundcell->iLastDisplay = Groundcell->iFrameNumber; // drugi raz nie potrzeba
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;
}
@@ -491,6 +462,9 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
bool
opengl_renderer::Render( TSubRect *Groundsubcell ) {
// oznaczanie aktywnych sektorów
Groundsubcell->LoadNodes();
Groundsubcell->RaAnimate(); // przeliczenia animacji torów w sektorze
TGroundNode *node;
@@ -906,23 +880,23 @@ opengl_renderer::Render_Alpha( TGround *Ground ) {
TGroundNode *node;
TSubRect *tmp;
// 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
tmp = *subcell;
tmp = subcellpair->second;
for( node = tmp->nRenderRectAlpha; node; node = node->nNext3 ) {
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
Render_Alpha( *subcell );
Render_Alpha( subcellpair->second );
}
::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
tmp = *subcell;
tmp = subcellpair->second;
for( node = tmp->nRenderWires; node; node = node->nNext3 ) {
Render_Alpha( node );
}
@@ -947,25 +921,9 @@ opengl_renderer::Render_Alpha( TSubRect *Groundsubcell ) {
return true;
}
// NOTE: legacy render system switch
#define _PROBLEND
bool
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// SPOSOB NA POZBYCIE SIE RAMKI DOOKOLA TEXTURY ALPHA DLA OBIEKTOW ZAGNIEZDZONYCH W SCN JAKO
// NODE
// W GROUND.H dajemy do klasy TGroundNode zmienna bool PROBLEND to samo robimy w klasie TGround
// nastepnie podczas wczytywania textury dla TRIANGLES w TGround::AddGroundNode
// sprawdzamy czy w nazwie jest @ i wg tego
// ustawiamy PROBLEND na true dla wlasnie wczytywanego trojkata (kazdy trojkat jest osobnym
// nodem)
// nastepnie podczas renderowania w bool TGroundNode::RenderAlpha()
// na poczatku ustawiamy standardowe GL_GREATER = 0.04
// pozniej sprawdzamy czy jest wlaczony PROBLEND dla aktualnie renderowanego noda TRIANGLE,
// wlasciwie dla kazdego node'a
// i jezeli tak to odpowiedni GL_GREATER w przeciwnym wypadku standardowy 0.04
double const distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
@@ -1029,14 +987,15 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
return false;
}
// setup
// w zaleznosci od koloru swiatla
auto const linewidth = clamp( 100.0 * Node->fLineThickness / ( distancesquared + 1.0 ), 1.0, 10.0 );
::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 ) ) ) ) );
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
std::min( 1.0, linewidth ) ) ) );
if( linewidth > 1.0 ) {
::glLineWidth( static_cast<float>(linewidth) );
}
GfxRenderer.Bind( 0 );
@@ -1048,6 +1007,10 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
m_geometry.draw( Node->m_geometry );
// post-render cleanup
if( linewidth > 1.0 ) {
::glLineWidth( 1.0f );
}
::glPopMatrix();
return true;
@@ -1059,13 +1022,6 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
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 );
@@ -1080,13 +1036,6 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// 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 );
}
#endif
return true;
}

View File

@@ -182,6 +182,8 @@ private:
typedef std::vector<opengl_light> opengllight_array;
typedef std::pair< double, TSubRect * > distancesubcell_pair;
// methods
bool
Init_caps();
@@ -226,7 +228,7 @@ private:
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
std::vector<distancesubcell_pair> m_drawqueue; // list of subcells to be drawn in current render pass
};

View File

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