mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 23:19:19 +02:00
build 170626. individual self-illumination levels for interior sections, automatic merging of suitable terrain geometry during load from text files, unused resource release by geometry bank manager, support for ui backgrounds with width:height ratio other than 4:3, comment parsing optimization, minor bug fixes
This commit is contained in:
89
DynObj.cpp
89
DynObj.cpp
@@ -527,6 +527,39 @@ void TDynamicObject::UpdateLeverEnum(TAnim *pAnim)
|
|||||||
pAnim->smAnimated->SetRotate(float3(1, 0, 0), pAnim->fParam[*pAnim->iIntBase]);
|
pAnim->smAnimated->SetRotate(float3(1, 0, 0), pAnim->fParam[*pAnim->iIntBase]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// sets light levels for registered interior sections
|
||||||
|
void
|
||||||
|
TDynamicObject::toggle_lights() {
|
||||||
|
|
||||||
|
if( true == SectionLightsActive ) {
|
||||||
|
// switch all lights off
|
||||||
|
for( auto §ionlight : SectionLightLevels ) {
|
||||||
|
sectionlight.level = 0.0f;
|
||||||
|
}
|
||||||
|
SectionLightsActive = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string compartmentname;
|
||||||
|
// set lights with probability depending on the compartment type. TODO: expose this in .mmd file
|
||||||
|
for( auto §ionlight : SectionLightLevels ) {
|
||||||
|
|
||||||
|
compartmentname = sectionlight.compartment->pName;
|
||||||
|
if( ( compartmentname.find( "corridor" ) != std::string::npos )
|
||||||
|
|| ( compartmentname.find( "korytarz" ) != std::string::npos ) ) {
|
||||||
|
// corridors are lit 100% of time
|
||||||
|
sectionlight.level = 0.75f;
|
||||||
|
}
|
||||||
|
else if(
|
||||||
|
( compartmentname.find( "compartment" ) != std::string::npos )
|
||||||
|
|| ( compartmentname.find( "przedzial" ) != std::string::npos ) ) {
|
||||||
|
// compartments are lit with 75% probability
|
||||||
|
sectionlight.level = ( Random() < 0.75 ? 0.75f : 0.05f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SectionLightsActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ABu 29.01.05 przeklejone z render i renderalpha: *********************
|
// ABu 29.01.05 przeklejone z render i renderalpha: *********************
|
||||||
void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
||||||
{ // ABu290105: pozbierane i uporzadkowane powtarzajace
|
{ // ABu290105: pozbierane i uporzadkowane powtarzajace
|
||||||
@@ -946,6 +979,13 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
|||||||
}
|
}
|
||||||
// else btHeadSignals23.TurnOff();
|
// else btHeadSignals23.TurnOff();
|
||||||
}
|
}
|
||||||
|
// interior light levels
|
||||||
|
for( auto const §ion : SectionLightLevels ) {
|
||||||
|
section.compartment->SetLightLevel( section.level, true );
|
||||||
|
if( section.load != nullptr ) {
|
||||||
|
section.load->SetLightLevel( section.level, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ABu 29.01.05 koniec przeklejenia *************************************
|
// ABu 29.01.05 koniec przeklejenia *************************************
|
||||||
|
|
||||||
@@ -1949,6 +1989,41 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
btMechanik1.Init("mechanik1", mdLowPolyInt, false);
|
btMechanik1.Init("mechanik1", mdLowPolyInt, false);
|
||||||
btMechanik2.Init("mechanik2", mdLowPolyInt, false);
|
btMechanik2.Init("mechanik2", mdLowPolyInt, false);
|
||||||
TurnOff(); // resetowanie zmiennych submodeli
|
TurnOff(); // resetowanie zmiennych submodeli
|
||||||
|
|
||||||
|
if( mdLowPolyInt != nullptr ) {
|
||||||
|
// check the low poly interior for potential compartments of interest, ie ones which can be individually lit
|
||||||
|
// TODO: definition of relevant compartments in the .mmd file
|
||||||
|
TSubModel *submodel { nullptr };
|
||||||
|
if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { SectionLightLevels.emplace_back( submodel, nullptr, 0.0f ); }
|
||||||
|
if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { SectionLightLevels.emplace_back( submodel, nullptr, 0.0f ); }
|
||||||
|
if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { SectionLightLevels.emplace_back( submodel, nullptr, 0.0f ); }
|
||||||
|
// passenger car compartments
|
||||||
|
std::vector<std::string> nameprefixes = { "corridor", "korytarz", "compartment", "przedzial" };
|
||||||
|
int compartmentindex;
|
||||||
|
std::string compartmentname;
|
||||||
|
for( auto const &nameprefix : nameprefixes ) {
|
||||||
|
compartmentindex = 0;
|
||||||
|
do {
|
||||||
|
compartmentname =
|
||||||
|
nameprefix + (
|
||||||
|
compartmentindex < 10 ?
|
||||||
|
"0" + std::to_string( compartmentindex ) :
|
||||||
|
std::to_string( compartmentindex ) );
|
||||||
|
submodel = mdLowPolyInt->GetFromName( compartmentname.c_str() );
|
||||||
|
if( submodel != nullptr ) {
|
||||||
|
// if specified compartment was found we check also for potential matching section in the currently assigned load
|
||||||
|
// NOTE: if the load gets changed this will invalidate stored pointers. TODO: rebuild the table on load change
|
||||||
|
SectionLightLevels.emplace_back(
|
||||||
|
submodel,
|
||||||
|
( mdLoad != nullptr ?
|
||||||
|
mdLoad->GetFromName( compartmentname.c_str() ):
|
||||||
|
nullptr ),
|
||||||
|
0.0f );
|
||||||
|
}
|
||||||
|
++compartmentindex;
|
||||||
|
} while( submodel != nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
// wyszukiwanie zderzakow
|
// wyszukiwanie zderzakow
|
||||||
if (mdModel) // jeśli ma w czym szukać
|
if (mdModel) // jeśli ma w czym szukać
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
@@ -3416,6 +3491,20 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
dDoorMoveR = 0;
|
dDoorMoveR = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compartment lights
|
||||||
|
/*
|
||||||
|
if( ( ctOwner != nullptr ?
|
||||||
|
ctOwner->Controlling()->Battery != SectionLightsActive :
|
||||||
|
MoverParameters->Battery != SectionLightsActive ) ) {
|
||||||
|
// if the vehicle has a controller, we base the light state on state of the controller otherwise we check the vehicle itself
|
||||||
|
*/
|
||||||
|
// the version above won't work as the vehicles don't turn batteries off :|
|
||||||
|
if( ( ctOwner != nullptr ?
|
||||||
|
ctOwner->Controlling()->Battery != SectionLightsActive :
|
||||||
|
SectionLightsActive == true ) ) { // without controller lights are off. NOTE: this likely mess up the EMU
|
||||||
|
toggle_lights();
|
||||||
|
}
|
||||||
|
|
||||||
// ABu-160303 sledzenie toru przed obiektem: *******************************
|
// ABu-160303 sledzenie toru przed obiektem: *******************************
|
||||||
// Z obserwacji: v>0 -> Coupler 0; v<0 ->coupler1 (Ra: prędkość jest związana
|
// Z obserwacji: v>0 -> Coupler 0; v<0 ->coupler1 (Ra: prędkość jest związana
|
||||||
// z pojazdem)
|
// z pojazdem)
|
||||||
|
|||||||
24
DynObj.h
24
DynObj.h
@@ -143,12 +143,8 @@ class TAnim
|
|||||||
struct material_data {
|
struct material_data {
|
||||||
|
|
||||||
int textures_alpha{ 0x30300030 }; // maska przezroczystości tekstur. default: tekstury wymienne nie mają przezroczystości
|
int textures_alpha{ 0x30300030 }; // maska przezroczystości tekstur. default: tekstury wymienne nie mają przezroczystości
|
||||||
texture_handle replacable_skins[ 5 ]; // McZapkie:zmienialne nadwozie
|
texture_handle replacable_skins[ 5 ] = { NULL, NULL, NULL, NULL, NULL }; // McZapkie:zmienialne nadwozie
|
||||||
int multi_textures{ 0 }; //<0 tekstury wskazane wpisem, >0 tekstury z przecinkami, =0 jedna
|
int multi_textures{ 0 }; //<0 tekstury wskazane wpisem, >0 tekstury z przecinkami, =0 jedna
|
||||||
|
|
||||||
material_data() {
|
|
||||||
::SecureZeroMemory( replacable_skins, sizeof( replacable_skins ) );
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TDynamicObject { // klasa pojazdu
|
class TDynamicObject { // klasa pojazdu
|
||||||
@@ -169,8 +165,7 @@ private: // położenie pojazdu w świecie oraz parametry ruchu
|
|||||||
float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia
|
float fAxleDist; // rozstaw wózków albo osi do liczenia proporcji zacienienia
|
||||||
vector3 modelRot; // obrot pudła względem świata - do przeanalizowania, czy potrzebne!!!
|
vector3 modelRot; // obrot pudła względem świata - do przeanalizowania, czy potrzebne!!!
|
||||||
// bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów
|
// bool bCameraNear; //blisko kamer są potrzebne dodatkowe obliczenia szczegółów
|
||||||
TDynamicObject * ABuFindNearestObject( TTrack *Track, TDynamicObject *MyPointer,
|
TDynamicObject * ABuFindNearestObject( TTrack *Track, TDynamicObject *MyPointer, int &CouplNr );
|
||||||
int &CouplNr );
|
|
||||||
|
|
||||||
public: // parametry położenia pojazdu dostępne publicznie
|
public: // parametry położenia pojazdu dostępne publicznie
|
||||||
std::string asTrack; // nazwa toru początkowego; wywalić?
|
std::string asTrack; // nazwa toru początkowego; wywalić?
|
||||||
@@ -193,6 +188,16 @@ public: // modele składowe pojazdu
|
|||||||
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
|
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
|
||||||
float3 InteriorLight { 0.9f * 255.0f / 255.0f, 0.9f * 216.0f / 255.0f, 0.9f * 176.0f / 255.0f }; // tungsten light. TODO: allow definition of light type?
|
float3 InteriorLight { 0.9f * 255.0f / 255.0f, 0.9f * 216.0f / 255.0f, 0.9f * 176.0f / 255.0f }; // tungsten light. TODO: allow definition of light type?
|
||||||
float InteriorLightLevel { 0.0f }; // current level of interior lighting
|
float InteriorLightLevel { 0.0f }; // current level of interior lighting
|
||||||
|
struct section_light {
|
||||||
|
TSubModel *compartment;
|
||||||
|
TSubModel *load;
|
||||||
|
float level;
|
||||||
|
section_light( TSubModel *Compartment, TSubModel *Load, float const Level ) :
|
||||||
|
compartment(Compartment), load(Load), level(Level)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
std::vector<section_light> SectionLightLevels; // table of light levels for specific compartments of associated 3d model
|
||||||
|
bool SectionLightsActive { false }; // flag indicating whether section lights were set.
|
||||||
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
|
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
|
||||||
|
|
||||||
private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
|
private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
|
||||||
@@ -200,7 +205,9 @@ public: // modele składowe pojazdu
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
inline
|
inline
|
||||||
material_data const *Material() const { return &m_materialdata; }
|
material_data const
|
||||||
|
*Material() const {
|
||||||
|
return &m_materialdata; }
|
||||||
// tymczasowo udostępnione do wyszukiwania drutu
|
// tymczasowo udostępnione do wyszukiwania drutu
|
||||||
int iAnimType[ ANIM_TYPES ]; // 0-osie,1-drzwi,2-obracane,3-zderzaki,4-wózki,5-pantografy,6-tłoki
|
int iAnimType[ ANIM_TYPES ]; // 0-osie,1-drzwi,2-obracane,3-zderzaki,4-wózki,5-pantografy,6-tłoki
|
||||||
private:
|
private:
|
||||||
@@ -226,6 +233,7 @@ public: // modele składowe pojazdu
|
|||||||
void UpdateLeverFloat(TAnim *pAnim); // animacja gałki zależna od float
|
void UpdateLeverFloat(TAnim *pAnim); // animacja gałki zależna od float
|
||||||
void UpdateLeverInt(TAnim *pAnim); // animacja gałki zależna od int (wartość)
|
void UpdateLeverInt(TAnim *pAnim); // animacja gałki zależna od int (wartość)
|
||||||
void UpdateLeverEnum(TAnim *pAnim); // animacja gałki zależna od int (lista kątów)
|
void UpdateLeverEnum(TAnim *pAnim); // animacja gałki zależna od int (lista kątów)
|
||||||
|
void toggle_lights(); // switch light levels for registered interior sections
|
||||||
private: // Ra: ciąg dalszy animacji, dopiero do ogarnięcia
|
private: // Ra: ciąg dalszy animacji, dopiero do ogarnięcia
|
||||||
// ABuWozki 060504
|
// ABuWozki 060504
|
||||||
vector3 bogieRot[2]; // Obroty wozkow w/m korpusu
|
vector3 bogieRot[2]; // Obroty wozkow w/m korpusu
|
||||||
|
|||||||
362
Ground.cpp
362
Ground.cpp
@@ -67,7 +67,6 @@ std::string LogComment;
|
|||||||
TGroundNode::TGroundNode()
|
TGroundNode::TGroundNode()
|
||||||
{ // nowy obiekt terenu - pusty
|
{ // nowy obiekt terenu - pusty
|
||||||
iType = GL_POINTS;
|
iType = GL_POINTS;
|
||||||
Vertices = NULL;
|
|
||||||
nNext = nNext2 = NULL;
|
nNext = nNext2 = NULL;
|
||||||
iCount = 0; // wierzchołków w trójkącie
|
iCount = 0; // wierzchołków w trójkącie
|
||||||
// iNumPts=0; //punktów w linii
|
// iNumPts=0; //punktów w linii
|
||||||
@@ -115,9 +114,6 @@ TGroundNode::~TGroundNode()
|
|||||||
break;
|
break;
|
||||||
case TP_TERRAIN:
|
case TP_TERRAIN:
|
||||||
{ // pierwsze nNode zawiera model E3D, reszta to trójkąty
|
{ // pierwsze nNode zawiera model E3D, reszta to trójkąty
|
||||||
for (int i = 1; i < iCount; ++i)
|
|
||||||
nNode->Vertices =
|
|
||||||
NULL; // zerowanie wskaźników w kolejnych elementach, bo nie są do usuwania
|
|
||||||
delete[] nNode; // usunięcie tablicy i pierwszego elementu
|
delete[] nNode; // usunięcie tablicy i pierwszego elementu
|
||||||
}
|
}
|
||||||
case TP_SUBMODEL: // dla formalności, nie wymaga usuwania
|
case TP_SUBMODEL: // dla formalności, nie wymaga usuwania
|
||||||
@@ -125,33 +121,31 @@ TGroundNode::~TGroundNode()
|
|||||||
case GL_LINES:
|
case GL_LINES:
|
||||||
case GL_LINE_STRIP:
|
case GL_LINE_STRIP:
|
||||||
case GL_LINE_LOOP:
|
case GL_LINE_LOOP:
|
||||||
SafeDeleteArray(Points);
|
|
||||||
break;
|
|
||||||
case GL_TRIANGLE_STRIP:
|
case GL_TRIANGLE_STRIP:
|
||||||
case GL_TRIANGLE_FAN:
|
case GL_TRIANGLE_FAN:
|
||||||
case GL_TRIANGLES:
|
case GL_TRIANGLES:
|
||||||
SafeDeleteArray(Vertices);
|
SafeDelete( Piece );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void TGroundNode::Init(int n)
|
void TGroundNode::Init(int n)
|
||||||
{ // utworzenie tablicy wierzchołków
|
{ // utworzenie tablicy wierzchołków
|
||||||
bVisible = false;
|
bVisible = false;
|
||||||
iNumVerts = n;
|
iNumVerts = n;
|
||||||
Vertices = new TGroundVertex[iNumVerts];
|
Vertices = new TGroundVertex[iNumVerts];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
TGroundNode::TGroundNode( TGroundNodeType t, int n ) :
|
TGroundNode::TGroundNode( TGroundNodeType t ) :
|
||||||
TGroundNode() {
|
TGroundNode() {
|
||||||
// utworzenie obiektu
|
// utworzenie obiektu
|
||||||
iNumVerts = n;
|
|
||||||
if( iNumVerts ) {
|
|
||||||
Vertices = new TGroundVertex[ iNumVerts ];
|
|
||||||
}
|
|
||||||
iType = t;
|
iType = t;
|
||||||
switch (iType) {
|
switch (iType) {
|
||||||
// zależnie od typu
|
// zależnie od typu
|
||||||
|
case GL_TRIANGLES: {
|
||||||
|
Piece = new piece_node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TP_TRACK: {
|
case TP_TRACK: {
|
||||||
pTrack = new TTrack( this );
|
pTrack = new TTrack( this );
|
||||||
break;
|
break;
|
||||||
@@ -171,36 +165,36 @@ void TGroundNode::InitNormals()
|
|||||||
switch (iType)
|
switch (iType)
|
||||||
{
|
{
|
||||||
case GL_TRIANGLE_STRIP:
|
case GL_TRIANGLE_STRIP:
|
||||||
v1 = Vertices[0].position - Vertices[1].position;
|
v1 = Piece->vertices[0].position - Piece->vertices[1].position;
|
||||||
v2 = Vertices[1].position - Vertices[2].position;
|
v2 = Piece->vertices[1].position - Piece->vertices[2].position;
|
||||||
n1 = glm::normalize(glm::cross(v1, v2));
|
n1 = glm::normalize(glm::cross(v1, v2));
|
||||||
if (Vertices[0].normal == glm::vec3())
|
if (Piece->vertices[0].normal == glm::vec3())
|
||||||
Vertices[0].normal = n1;
|
Piece->vertices[0].normal = n1;
|
||||||
v3 = Vertices[2].position - Vertices[3].position;
|
v3 = Piece->vertices[2].position - Piece->vertices[3].position;
|
||||||
n2 = glm::normalize(glm::cross(v3, v2));
|
n2 = glm::normalize(glm::cross(v3, v2));
|
||||||
if (Vertices[1].normal == glm::vec3())
|
if (Piece->vertices[1].normal == glm::vec3())
|
||||||
Vertices[1].normal = (n1 + n2) * 0.5f;
|
Piece->vertices[1].normal = (n1 + n2) * 0.5f;
|
||||||
|
|
||||||
for ( i = 2; i < iNumVerts - 2; i += 2)
|
for ( i = 2; i < iNumVerts - 2; i += 2)
|
||||||
{
|
{
|
||||||
v4 = Vertices[i - 1].position - Vertices[i].position;
|
v4 = Piece->vertices[i - 1].position - Piece->vertices[i].position;
|
||||||
v5 = Vertices[i].position - Vertices[i + 1].position;
|
v5 = Piece->vertices[i].position - Piece->vertices[i + 1].position;
|
||||||
n3 = glm::normalize(glm::cross(v3, v4));
|
n3 = glm::normalize(glm::cross(v3, v4));
|
||||||
n4 = glm::normalize(glm::cross(v5, v4));
|
n4 = glm::normalize(glm::cross(v5, v4));
|
||||||
if (Vertices[i].normal == glm::vec3())
|
if (Piece->vertices[i].normal == glm::vec3())
|
||||||
Vertices[i].normal = (n1 + n2 + n3) / 3.0f;
|
Piece->vertices[i].normal = (n1 + n2 + n3) / 3.0f;
|
||||||
if (Vertices[i + 1].normal == glm::vec3())
|
if (Piece->vertices[i + 1].normal == glm::vec3())
|
||||||
Vertices[i + 1].normal = (n2 + n3 + n4) / 3.0f;
|
Piece->vertices[i + 1].normal = (n2 + n3 + n4) / 3.0f;
|
||||||
n1 = n3;
|
n1 = n3;
|
||||||
n2 = n4;
|
n2 = n4;
|
||||||
v3 = v5;
|
v3 = v5;
|
||||||
}
|
}
|
||||||
if (Vertices[i].normal == glm::vec3())
|
if (Piece->vertices[i].normal == glm::vec3())
|
||||||
Vertices[i].normal = (n1 + n2) / 2.0f;
|
Piece->vertices[i].normal = (n1 + n2) / 2.0f;
|
||||||
if (i + 1 < iNumVerts)
|
if (i + 1 < iNumVerts)
|
||||||
{
|
{
|
||||||
if (Vertices[i + 1].normal == glm::vec3())
|
if (Piece->vertices[i + 1].normal == glm::vec3())
|
||||||
Vertices[i + 1].normal = n2;
|
Piece->vertices[i + 1].normal = n2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
WriteLog("odd number of vertices, normals may be wrong!");
|
WriteLog("odd number of vertices, normals may be wrong!");
|
||||||
@@ -212,21 +206,21 @@ void TGroundNode::InitNormals()
|
|||||||
case GL_TRIANGLES:
|
case GL_TRIANGLES:
|
||||||
for (i = 0; i < iNumVerts; i += 3)
|
for (i = 0; i < iNumVerts; i += 3)
|
||||||
{
|
{
|
||||||
v1 = Vertices[i + 0].position - Vertices[i + 1].position;
|
v1 = Piece->vertices[i + 0].position - Piece->vertices[i + 1].position;
|
||||||
v2 = Vertices[i + 1].position - Vertices[i + 2].position;
|
v2 = Piece->vertices[i + 1].position - Piece->vertices[i + 2].position;
|
||||||
n1 = glm::normalize(glm::cross(v1, v2));
|
n1 = glm::normalize(glm::cross(v1, v2));
|
||||||
if (Vertices[i + 0].normal == glm::vec3())
|
if( Piece->vertices[i + 0].normal == glm::vec3() )
|
||||||
Vertices[i + 0].normal = (n1);
|
Piece->vertices[i + 0].normal = (n1);
|
||||||
if (Vertices[i + 1].normal == glm::vec3())
|
if( Piece->vertices[i + 1].normal == glm::vec3() )
|
||||||
Vertices[i + 1].normal = (n1);
|
Piece->vertices[i + 1].normal = (n1);
|
||||||
if (Vertices[i + 2].normal == glm::vec3())
|
if( Piece->vertices[i + 2].normal == glm::vec3() )
|
||||||
Vertices[i + 2].normal = (n1);
|
Piece->vertices[i + 2].normal = (n1);
|
||||||
t1 = glm::vec2(
|
t1 = glm::vec2(
|
||||||
std::floor( Vertices[ i + 0 ].texture.s ),
|
std::floor( Piece->vertices[ i + 0 ].texture.s ),
|
||||||
std::floor( Vertices[ i + 0 ].texture.t ) );
|
std::floor( Piece->vertices[ i + 0 ].texture.t ) );
|
||||||
Vertices[ i + 1 ].texture -= t1;
|
Piece->vertices[ i + 1 ].texture -= t1;
|
||||||
Vertices[ i + 2 ].texture -= t1;
|
Piece->vertices[ i + 2 ].texture -= t1;
|
||||||
Vertices[ i + 0 ].texture -= t1;
|
Piece->vertices[ i + 0 ].texture -= t1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -349,8 +343,10 @@ void TSubRect::NodeAdd(TGroundNode *Node)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case TP_TRACTIONPOWERSOURCE: // a te w ogóle pomijamy
|
case TP_TRACTIONPOWERSOURCE: // a te w ogóle pomijamy
|
||||||
|
/*
|
||||||
// case TP_ISOLATED: //lista torów w obwodzie izolowanym - na razie ignorowana
|
// case TP_ISOLATED: //lista torów w obwodzie izolowanym - na razie ignorowana
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
case TP_DYNAMIC:
|
case TP_DYNAMIC:
|
||||||
return; // tych nie dopisujemy wcale
|
return; // tych nie dopisujemy wcale
|
||||||
}
|
}
|
||||||
@@ -380,22 +376,14 @@ void TSubRect::Sort() {
|
|||||||
|
|
||||||
TTrack * TSubRect::FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude)
|
TTrack * TSubRect::FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude)
|
||||||
{ // szukanie toru, którego koniec jest najbliższy (*Point)
|
{ // szukanie toru, którego koniec jest najbliższy (*Point)
|
||||||
for (int i = 0; i < iTracks; ++i)
|
for( int i = 0; i < iTracks; ++i ) {
|
||||||
if( tTracks[ i ] != Exclude ) // można użyć tabelę torów, bo jest mniejsza
|
if( tTracks[ i ] != Exclude ) // można użyć tabelę torów, bo jest mniejsza
|
||||||
{
|
{
|
||||||
iConnection = tTracks[ i ]->TestPoint( Point );
|
iConnection = tTracks[ i ]->TestPoint( Point );
|
||||||
if( iConnection >= 0 )
|
if( iConnection >= 0 )
|
||||||
return tTracks[ i ]; // szukanie TGroundNode nie jest potrzebne
|
return tTracks[ i ]; // szukanie TGroundNode nie jest potrzebne
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
TGroundNode *Current;
|
|
||||||
for (Current=nRootNode;Current;Current=Current->Next)
|
|
||||||
if ((Current->iType==TP_TRACK)&&(Current->pTrack!=Exclude)) //można użyć tabelę torów
|
|
||||||
{
|
|
||||||
iConnection=Current->pTrack->TestPoint(Point);
|
|
||||||
if (iConnection>=0) return Current;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -449,30 +437,20 @@ void TSubRect::LoadNodes() {
|
|||||||
auto *node { nRootNode };
|
auto *node { nRootNode };
|
||||||
while( node != nullptr ) {
|
while( node != nullptr ) {
|
||||||
switch (node->iType) {
|
switch (node->iType) {
|
||||||
case GL_TRIANGLES: {
|
case GL_TRIANGLES:
|
||||||
vertex_array vertices;
|
|
||||||
for( int idx = 0; idx < node->iNumVerts; ++idx ) {
|
|
||||||
vertices.emplace_back(
|
|
||||||
node->Vertices[ idx ].position - node->m_rootposition,
|
|
||||||
node->Vertices[ idx ].normal,
|
|
||||||
node->Vertices[ idx ].texture );
|
|
||||||
}
|
|
||||||
node->m_geometry = GfxRenderer.Insert( vertices, m_geometrybank, GL_TRIANGLES );
|
|
||||||
SafeDeleteArray( node->Vertices );
|
|
||||||
node->iNumVerts = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GL_LINES: {
|
case GL_LINES: {
|
||||||
vertex_array vertices;
|
vertex_array vertices;
|
||||||
for( int idx = 0; idx < node->iNumPts; ++idx ) {
|
for( auto const &vertex : node->Piece->vertices ) {
|
||||||
vertices.emplace_back(
|
vertices.emplace_back(
|
||||||
node->Points[ idx ] - node->m_rootposition,
|
vertex.position - node->m_rootposition,
|
||||||
glm::vec3(),
|
vertex.normal,
|
||||||
glm::vec2() );
|
vertex.texture );
|
||||||
}
|
}
|
||||||
node->m_geometry = GfxRenderer.Insert( vertices, m_geometrybank, GL_LINES );
|
node->Piece->geometry = GfxRenderer.Insert( vertices, m_geometrybank, node->iType );
|
||||||
SafeDeleteArray( node->Vertices );
|
node->Piece->vertices.swap( std::vector<TGroundVertex>() ); // hipster shrink_to_fit
|
||||||
node->iNumPts = 0;
|
// TODO: get rid of the vertex counters, they're obsolete at this point
|
||||||
|
if( node->iType == GL_LINES ) { node->iNumVerts = 0; }
|
||||||
|
else { node->iNumPts = 0; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TP_TRACK:
|
case TP_TRACK:
|
||||||
@@ -529,6 +507,59 @@ TGroundRect::Init() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// dodanie obiektu do sektora na etapie rozdzielania na sektory
|
||||||
|
void
|
||||||
|
TGroundRect::NodeAdd( TGroundNode *Node ) {
|
||||||
|
|
||||||
|
// override visibility ranges, to ensure the content is drawn from far enough
|
||||||
|
Node->fSquareRadius = 50000.0 * 50000.0;
|
||||||
|
Node->fSquareMinRadius = 0.0;
|
||||||
|
|
||||||
|
// if the cell already has a node with matching material settings, we can just add the new geometry to it
|
||||||
|
if( ( Node->iType == GL_TRIANGLES ) ) {
|
||||||
|
// cell node only receives opaque geometry, so we can skip transparency test
|
||||||
|
auto matchingnode { nRenderRect };
|
||||||
|
while( ( matchingnode != nullptr )
|
||||||
|
&& ( false == mergeable( *Node, *matchingnode ) ) ) {
|
||||||
|
// search will get us either a matching node, or a nullptr
|
||||||
|
matchingnode = matchingnode->nNext3;
|
||||||
|
}
|
||||||
|
if( matchingnode != nullptr ) {
|
||||||
|
// a valid match, so dump the content into it
|
||||||
|
// updating centre points isn't strictly necessary since render is based off the cell's middle, but, eh
|
||||||
|
matchingnode->pCenter =
|
||||||
|
interpolate(
|
||||||
|
matchingnode->pCenter, Node->pCenter,
|
||||||
|
static_cast<float>( Node->iNumVerts ) / ( Node->iNumVerts + matchingnode->iNumVerts ) );
|
||||||
|
matchingnode->iNumVerts += Node->iNumVerts;
|
||||||
|
matchingnode->Piece->vertices.resize( matchingnode->iNumVerts, TGroundVertex() );
|
||||||
|
matchingnode->Piece->vertices.insert(
|
||||||
|
std::end( matchingnode->Piece->vertices ),
|
||||||
|
std::begin( Node->Piece->vertices ), std::end( Node->Piece->vertices ) );
|
||||||
|
// clear content of the node we're copying. a minor memory saving at best, but still a saving
|
||||||
|
Node->Piece->vertices.swap( std::vector<TGroundVertex>() );
|
||||||
|
Node->iNumVerts = 0;
|
||||||
|
// since we've put the data in existing node we can skip adding the new one...
|
||||||
|
return;
|
||||||
|
// ...for others, they'll go through the regular procedure, along with other non-mergeable types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSubRect::NodeAdd( Node );
|
||||||
|
}
|
||||||
|
|
||||||
|
// compares two provided nodes, returns true if their content can be merged
|
||||||
|
bool
|
||||||
|
TGroundRect::mergeable( TGroundNode const &Left, TGroundNode const &Right ) {
|
||||||
|
// since view ranges and transparency type for all nodes put through this method are guaranteed to be equal,
|
||||||
|
// we can skip their tests and only do the material check.
|
||||||
|
// TODO, TBD: material as dedicated type, and refactor this method into a simple equality test
|
||||||
|
return ( ( Left.TextureID == Right.TextureID )
|
||||||
|
&& ( Left.Ambient == Right.Ambient )
|
||||||
|
&& ( Left.Diffuse == Right.Diffuse )
|
||||||
|
&& ( Left.Specular == Right.Specular ) );
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
BYTE TempConnectionType[ 200 ]; // Ra: sprzêgi w sk³adzie; ujemne, gdy odwrotnie
|
BYTE TempConnectionType[ 200 ]; // Ra: sprzêgi w sk³adzie; ujemne, gdy odwrotnie
|
||||||
@@ -594,19 +625,19 @@ void TGround::Free()
|
|||||||
nRootDynamic = NULL;
|
nRootDynamic = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TGroundNode * TGround::DynamicFindAny(std::string asNameToFind)
|
TGroundNode * TGround::DynamicFindAny(std::string const &Name)
|
||||||
{ // wyszukanie pojazdu o podanej nazwie, szukanie po wszystkich (użyć drzewa!)
|
{ // wyszukanie pojazdu o podanej nazwie, szukanie po wszystkich (użyć drzewa!)
|
||||||
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
||||||
if ((Current->asName == asNameToFind))
|
if ((Current->asName == Name))
|
||||||
return Current;
|
return Current;
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
TGroundNode * TGround::DynamicFind(std::string asNameToFind)
|
TGroundNode * TGround::DynamicFind(std::string const &Name)
|
||||||
{ // wyszukanie pojazdu z obsadą o podanej nazwie (użyć drzewa!)
|
{ // wyszukanie pojazdu z obsadą o podanej nazwie (użyć drzewa!)
|
||||||
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
for (TGroundNode *Current = nRootDynamic; Current; Current = Current->nNext)
|
||||||
if (Current->DynamicObject->Mechanik)
|
if (Current->DynamicObject->Mechanik)
|
||||||
if ((Current->asName == asNameToFind))
|
if ((Current->asName == Name))
|
||||||
return Current;
|
return Current;
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
@@ -685,12 +716,12 @@ void TGround::RaTriangleDivider(TGroundNode *node)
|
|||||||
double x1 = x0 + 1400.0;
|
double x1 = x0 + 1400.0;
|
||||||
double z0 = 1000.0 * std::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;
|
double z1 = z0 + 1400.0;
|
||||||
if ((node->Vertices[0].position.x >= x0) && (node->Vertices[0].position.x <= x1) &&
|
if ((node->Piece->vertices[0].position.x >= x0) && (node->Piece->vertices[0].position.x <= x1) &&
|
||||||
(node->Vertices[0].position.z >= z0) && (node->Vertices[0].position.z <= z1) &&
|
(node->Piece->vertices[0].position.z >= z0) && (node->Piece->vertices[0].position.z <= z1) &&
|
||||||
(node->Vertices[1].position.x >= x0) && (node->Vertices[1].position.x <= x1) &&
|
(node->Piece->vertices[1].position.x >= x0) && (node->Piece->vertices[1].position.x <= x1) &&
|
||||||
(node->Vertices[1].position.z >= z0) && (node->Vertices[1].position.z <= z1) &&
|
(node->Piece->vertices[1].position.z >= z0) && (node->Piece->vertices[1].position.z <= z1) &&
|
||||||
(node->Vertices[2].position.x >= x0) && (node->Vertices[2].position.x <= x1) &&
|
(node->Piece->vertices[2].position.x >= x0) && (node->Piece->vertices[2].position.x <= x1) &&
|
||||||
(node->Vertices[2].position.z >= z0) && (node->Vertices[2].position.z <= z1))
|
(node->Piece->vertices[2].position.z >= z0) && (node->Piece->vertices[2].position.z <= z1))
|
||||||
return; // trójkąt wystający mniej niż 200m z kw. kilometrowego jest do przyjęcia
|
return; // trójkąt wystający mniej niż 200m z kw. kilometrowego jest do przyjęcia
|
||||||
// Ra: przerobić na dzielenie na 2 trójkąty, podział w przecięciu z siatką kilometrową
|
// Ra: przerobić na dzielenie na 2 trójkąty, podział w przecięciu z siatką kilometrową
|
||||||
// Ra: i z rekurencją będzie dzielić trzy trójkąty, jeśli będzie taka potrzeba
|
// Ra: i z rekurencją będzie dzielić trzy trójkąty, jeśli będzie taka potrzeba
|
||||||
@@ -700,47 +731,46 @@ void TGround::RaTriangleDivider(TGroundNode *node)
|
|||||||
x1 -= 200.0; // przestawienie na siatkę
|
x1 -= 200.0; // przestawienie na siatkę
|
||||||
z0 += 200.0;
|
z0 += 200.0;
|
||||||
z1 -= 200.0;
|
z1 -= 200.0;
|
||||||
mul = (node->Vertices[0].position.x - x0) * (node->Vertices[1].position.x - x0); // AB na wschodzie
|
mul = (node->Piece->vertices[0].position.x - x0) * (node->Piece->vertices[1].position.x - x0); // AB na wschodzie
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 0;
|
min = mul, divide = 0;
|
||||||
mul = (node->Vertices[1].position.x - x0) * (node->Vertices[2].position.x - x0); // BC na wschodzie
|
mul = (node->Piece->vertices[1].position.x - x0) * (node->Piece->vertices[2].position.x - x0); // BC na wschodzie
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 1;
|
min = mul, divide = 1;
|
||||||
mul = (node->Vertices[2].position.x - x0) * (node->Vertices[0].position.x - x0); // CA na wschodzie
|
mul = (node->Piece->vertices[2].position.x - x0) * (node->Piece->vertices[0].position.x - x0); // CA na wschodzie
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 2;
|
min = mul, divide = 2;
|
||||||
mul = (node->Vertices[0].position.x - x1) * (node->Vertices[1].position.x - x1); // AB na zachodzie
|
mul = (node->Piece->vertices[0].position.x - x1) * (node->Piece->vertices[1].position.x - x1); // AB na zachodzie
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 8;
|
min = mul, divide = 8;
|
||||||
mul = (node->Vertices[1].position.x - x1) * (node->Vertices[2].position.x - x1); // BC na zachodzie
|
mul = (node->Piece->vertices[1].position.x - x1) * (node->Piece->vertices[2].position.x - x1); // BC na zachodzie
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 9;
|
min = mul, divide = 9;
|
||||||
mul = (node->Vertices[2].position.x - x1) * (node->Vertices[0].position.x - x1); // CA na zachodzie
|
mul = (node->Piece->vertices[2].position.x - x1) * (node->Piece->vertices[0].position.x - x1); // CA na zachodzie
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 10;
|
min = mul, divide = 10;
|
||||||
mul = (node->Vertices[0].position.z - z0) * (node->Vertices[1].position.z - z0); // AB na południu
|
mul = (node->Piece->vertices[0].position.z - z0) * (node->Piece->vertices[1].position.z - z0); // AB na południu
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 4;
|
min = mul, divide = 4;
|
||||||
mul = (node->Vertices[1].position.z - z0) * (node->Vertices[2].position.z - z0); // BC na południu
|
mul = (node->Piece->vertices[1].position.z - z0) * (node->Piece->vertices[2].position.z - z0); // BC na południu
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 5;
|
min = mul, divide = 5;
|
||||||
mul = (node->Vertices[2].position.z - z0) * (node->Vertices[0].position.z - z0); // CA na południu
|
mul = (node->Piece->vertices[2].position.z - z0) * (node->Piece->vertices[0].position.z - z0); // CA na południu
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 6;
|
min = mul, divide = 6;
|
||||||
mul = (node->Vertices[0].position.z - z1) * (node->Vertices[1].position.z - z1); // AB na północy
|
mul = (node->Piece->vertices[0].position.z - z1) * (node->Piece->vertices[1].position.z - z1); // AB na północy
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 12;
|
min = mul, divide = 12;
|
||||||
mul = (node->Vertices[1].position.z - z1) * (node->Vertices[2].position.z - z1); // BC na północy
|
mul = (node->Piece->vertices[1].position.z - z1) * (node->Piece->vertices[2].position.z - z1); // BC na północy
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
min = mul, divide = 13;
|
min = mul, divide = 13;
|
||||||
mul = (node->Vertices[2].position.z - z1) * (node->Vertices[0].position.z - z1); // CA na północy
|
mul = (node->Piece->vertices[2].position.z - z1) * (node->Piece->vertices[0].position.z - z1); // CA na północy
|
||||||
if (mul < min)
|
if (mul < min)
|
||||||
divide = 14;
|
divide = 14;
|
||||||
// tworzymy jeden dodatkowy trójkąt, dzieląc jeden bok na przecięciu siatki kilometrowej
|
// tworzymy jeden dodatkowy trójkąt, dzieląc jeden bok na przecięciu siatki kilometrowej
|
||||||
TGroundNode *ntri; // wskaźnik na nowy trójkąt
|
TGroundNode *ntri; // wskaźnik na nowy trójkąt
|
||||||
ntri = new TGroundNode(); // a ten jest nowy
|
ntri = new TGroundNode(GL_TRIANGLES); // a ten jest nowy
|
||||||
ntri->iType = GL_TRIANGLES; // kopiowanie parametrów, przydałby się konstruktor kopiujący
|
// kopiowanie parametrów, przydałby się konstruktor kopiujący
|
||||||
ntri->Init(3);
|
|
||||||
ntri->TextureID = node->TextureID;
|
ntri->TextureID = node->TextureID;
|
||||||
ntri->iFlags = node->iFlags;
|
ntri->iFlags = node->iFlags;
|
||||||
ntri->Ambient = node->Ambient;
|
ntri->Ambient = node->Ambient;
|
||||||
@@ -753,42 +783,44 @@ void TGround::RaTriangleDivider(TGroundNode *node)
|
|||||||
ntri->nNext = nRootOfType[GL_TRIANGLES];
|
ntri->nNext = nRootOfType[GL_TRIANGLES];
|
||||||
nRootOfType[GL_TRIANGLES] = ntri; // dopisanie z przodu do listy
|
nRootOfType[GL_TRIANGLES] = ntri; // dopisanie z przodu do listy
|
||||||
++iNumNodes;
|
++iNumNodes;
|
||||||
|
ntri->iNumVerts = 3;
|
||||||
|
ntri->Piece->vertices.resize( 3 );
|
||||||
switch (divide & 3)
|
switch (divide & 3)
|
||||||
{ // podzielenie jednego z boków, powstaje wierzchołek D
|
{ // podzielenie jednego z boków, powstaje wierzchołek D
|
||||||
case 0: // podział AB (0-1) -> ADC i DBC
|
case 0: // podział AB (0-1) -> ADC i DBC
|
||||||
ntri->Vertices[2] = node->Vertices[2]; // wierzchołek C jest wspólny
|
ntri->Piece->vertices[2] = node->Piece->vertices[2]; // wierzchołek C jest wspólny
|
||||||
ntri->Vertices[1] = node->Vertices[1]; // wierzchołek B przechodzi do nowego
|
ntri->Piece->vertices[1] = node->Piece->vertices[1]; // wierzchołek B przechodzi do nowego
|
||||||
// node->Vertices[1].HalfSet(node->Vertices[0],node->Vertices[1]); //na razie D tak
|
// node->Vertices[1].HalfSet(node->Vertices[0],node->Vertices[1]); //na razie D tak
|
||||||
if (divide & 4)
|
if (divide & 4)
|
||||||
node->Vertices[1].SetByZ(node->Vertices[0], node->Vertices[1], (divide & 8) ? z1 : z0);
|
node->Piece->vertices[1].SetByZ(node->Piece->vertices[0], node->Piece->vertices[1], (divide & 8) ? z1 : z0);
|
||||||
else
|
else
|
||||||
node->Vertices[1].SetByX(node->Vertices[0], node->Vertices[1], (divide & 8) ? x1 : x0);
|
node->Piece->vertices[1].SetByX(node->Piece->vertices[0], node->Piece->vertices[1], (divide & 8) ? x1 : x0);
|
||||||
ntri->Vertices[0] = node->Vertices[1]; // wierzchołek D jest wspólny
|
ntri->Piece->vertices[0] = node->Piece->vertices[1]; // wierzchołek D jest wspólny
|
||||||
break;
|
break;
|
||||||
case 1: // podział BC (1-2) -> ABD i ADC
|
case 1: // podział BC (1-2) -> ABD i ADC
|
||||||
ntri->Vertices[0] = node->Vertices[0]; // wierzchołek A jest wspólny
|
ntri->Piece->vertices[0] = node->Piece->vertices[0]; // wierzchołek A jest wspólny
|
||||||
ntri->Vertices[2] = node->Vertices[2]; // wierzchołek C przechodzi do nowego
|
ntri->Piece->vertices[2] = node->Piece->vertices[2]; // wierzchołek C przechodzi do nowego
|
||||||
// node->Vertices[2].HalfSet(node->Vertices[1],node->Vertices[2]); //na razie D tak
|
// node->Vertices[2].HalfSet(node->Vertices[1],node->Vertices[2]); //na razie D tak
|
||||||
if (divide & 4)
|
if (divide & 4)
|
||||||
node->Vertices[2].SetByZ(node->Vertices[1], node->Vertices[2], (divide & 8) ? z1 : z0);
|
node->Piece->vertices[2].SetByZ(node->Piece->vertices[1], node->Piece->vertices[2], (divide & 8) ? z1 : z0);
|
||||||
else
|
else
|
||||||
node->Vertices[2].SetByX(node->Vertices[1], node->Vertices[2], (divide & 8) ? x1 : x0);
|
node->Piece->vertices[2].SetByX(node->Piece->vertices[1], node->Piece->vertices[2], (divide & 8) ? x1 : x0);
|
||||||
ntri->Vertices[1] = node->Vertices[2]; // wierzchołek D jest wspólny
|
ntri->Piece->vertices[1] = node->Piece->vertices[2]; // wierzchołek D jest wspólny
|
||||||
break;
|
break;
|
||||||
case 2: // podział CA (2-0) -> ABD i DBC
|
case 2: // podział CA (2-0) -> ABD i DBC
|
||||||
ntri->Vertices[1] = node->Vertices[1]; // wierzchołek B jest wspólny
|
ntri->Piece->vertices[1] = node->Piece->vertices[1]; // wierzchołek B jest wspólny
|
||||||
ntri->Vertices[2] = node->Vertices[2]; // wierzchołek C przechodzi do nowego
|
ntri->Piece->vertices[2] = node->Piece->vertices[2]; // wierzchołek C przechodzi do nowego
|
||||||
// node->Vertices[2].HalfSet(node->Vertices[2],node->Vertices[0]); //na razie D tak
|
// node->Vertices[2].HalfSet(node->Vertices[2],node->Vertices[0]); //na razie D tak
|
||||||
if (divide & 4)
|
if (divide & 4)
|
||||||
node->Vertices[2].SetByZ(node->Vertices[2], node->Vertices[0], (divide & 8) ? z1 : z0);
|
node->Piece->vertices[2].SetByZ(node->Piece->vertices[2], node->Piece->vertices[0], (divide & 8) ? z1 : z0);
|
||||||
else
|
else
|
||||||
node->Vertices[2].SetByX(node->Vertices[2], node->Vertices[0], (divide & 8) ? x1 : x0);
|
node->Piece->vertices[2].SetByX(node->Piece->vertices[2], node->Piece->vertices[0], (divide & 8) ? x1 : x0);
|
||||||
ntri->Vertices[0] = node->Vertices[2]; // wierzchołek D jest wspólny
|
ntri->Piece->vertices[0] = node->Piece->vertices[2]; // wierzchołek D jest wspólny
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// przeliczenie środków ciężkości obu
|
// przeliczenie środków ciężkości obu
|
||||||
node->pCenter = ( node->Vertices[ 0 ].position + node->Vertices[ 1 ].position + node->Vertices[ 2 ].position ) / 3.0;
|
node->pCenter = ( node->Piece->vertices[ 0 ].position + node->Piece->vertices[ 1 ].position + node->Piece->vertices[ 2 ].position ) / 3.0;
|
||||||
ntri->pCenter = ( ntri->Vertices[ 0 ].position + ntri->Vertices[ 1 ].position + ntri->Vertices[ 2 ].position ) / 3.0;
|
ntri->pCenter = ( ntri->Piece->vertices[ 0 ].position + ntri->Piece->vertices[ 1 ].position + ntri->Piece->vertices[ 2 ].position ) / 3.0;
|
||||||
RaTriangleDivider(node); // rekurencja, bo nawet na TD raz nie wystarczy
|
RaTriangleDivider(node); // rekurencja, bo nawet na TD raz nie wystarczy
|
||||||
RaTriangleDivider(ntri);
|
RaTriangleDivider(ntri);
|
||||||
};
|
};
|
||||||
@@ -1218,7 +1250,6 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
tmp->nNode[i].iFlags = 0x10; // nieprzezroczyste; nie usuwany
|
tmp->nNode[i].iFlags = 0x10; // nieprzezroczyste; nie usuwany
|
||||||
tmp->nNode[i].bVisible = true;
|
tmp->nNode[i].bVisible = true;
|
||||||
tmp->nNode[i].pCenter = tmp->pCenter; // nie przesuwamy w inne miejsce
|
tmp->nNode[i].pCenter = tmp->pCenter; // nie przesuwamy w inne miejsce
|
||||||
// tmp->nNode[i].asName=
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!tmp->asName.empty()) // jest pusta gdy "none"
|
else if (!tmp->asName.empty()) // jest pusta gdy "none"
|
||||||
@@ -1291,18 +1322,6 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
&& ( true == GfxRenderer.Texture( tmp->TextureID ).has_alpha ) ) ?
|
&& ( true == GfxRenderer.Texture( tmp->TextureID ).has_alpha ) ) ?
|
||||||
0x20 :
|
0x20 :
|
||||||
0x10 );
|
0x10 );
|
||||||
|
|
||||||
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, vertex1, vertex2;
|
TGroundVertex vertex, vertex1, vertex2;
|
||||||
std::size_t vertexcount { 0 };
|
std::size_t vertexcount { 0 };
|
||||||
@@ -1346,9 +1365,17 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||||
else if( vertexcount >= 2 ) {
|
else if( vertexcount >= 2 ) {
|
||||||
|
// swap order every other triangle, to maintain consistent winding
|
||||||
|
if( vertexcount % 2 == 0 ) {
|
||||||
importedvertices.emplace_back( vertex1 );
|
importedvertices.emplace_back( vertex1 );
|
||||||
importedvertices.emplace_back( vertex2 );
|
importedvertices.emplace_back( vertex2 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
importedvertices.emplace_back( vertex2 );
|
||||||
|
importedvertices.emplace_back( vertex1 );
|
||||||
|
}
|
||||||
importedvertices.emplace_back( vertex );
|
importedvertices.emplace_back( vertex );
|
||||||
|
|
||||||
vertex1 = vertex2;
|
vertex1 = vertex2;
|
||||||
vertex2 = vertex;
|
vertex2 = vertex;
|
||||||
}
|
}
|
||||||
@@ -1363,25 +1390,27 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
} while (token.compare("endtri") != 0);
|
} while (token.compare("endtri") != 0);
|
||||||
|
|
||||||
tmp->iType = GL_TRIANGLES;
|
tmp->iType = GL_TRIANGLES;
|
||||||
|
tmp->Piece = new piece_node();
|
||||||
|
tmp->iNumVerts = importedvertices.size();
|
||||||
|
|
||||||
auto const nv = importedvertices.size();
|
if( tmp->iNumVerts > 0 ) {
|
||||||
tmp->Init(nv); // utworzenie tablicy wierzchołków
|
|
||||||
|
|
||||||
for( std::size_t i = 0; i < nv; ++i ) {
|
tmp->Piece->vertices.swap( importedvertices );
|
||||||
tmp->pCenter += importedvertices[ i ].position;
|
|
||||||
|
for( auto const &vertex : tmp->Piece->vertices ) {
|
||||||
|
tmp->pCenter += vertex.position;
|
||||||
}
|
}
|
||||||
tmp->pCenter /= (nv > 0 ? nv : 1);
|
tmp->pCenter /= tmp->iNumVerts;
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
for (std::size_t i = 0; i < nv; ++i)
|
for( auto const &vertex : tmp->Piece->vertices ) {
|
||||||
{
|
tf = SquareMagnitude( vertex.position - tmp->pCenter );
|
||||||
tmp->Vertices[i] = importedvertices[i];
|
|
||||||
tf = SquareMagnitude( tmp->Vertices[ i ].position - tmp->pCenter );
|
|
||||||
if( tf > r )
|
if( tf > r )
|
||||||
r = tf;
|
r = tf;
|
||||||
}
|
}
|
||||||
tmp->fSquareRadius += r;
|
tmp->fSquareRadius += r;
|
||||||
RaTriangleDivider( tmp ); // Ra: dzielenie trójkątów jest teraz całkiem wydajne
|
RaTriangleDivider( tmp ); // Ra: dzielenie trójkątów jest teraz całkiem wydajne
|
||||||
|
}
|
||||||
} // koniec wczytywania trójkątów
|
} // koniec wczytywania trójkątów
|
||||||
break;
|
break;
|
||||||
case GL_LINES:
|
case GL_LINES:
|
||||||
@@ -1394,6 +1423,7 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
>> tmp->Diffuse.b
|
>> tmp->Diffuse.b
|
||||||
>> tmp->fLineThickness;
|
>> tmp->fLineThickness;
|
||||||
tmp->Diffuse /= 255.0f;
|
tmp->Diffuse /= 255.0f;
|
||||||
|
tmp->fLineThickness = std::min( 30.0, tmp->fLineThickness ); // 30 pix equals rougly width of a signal pole viewed from ~1m away
|
||||||
|
|
||||||
TGroundVertex vertex, vertex0, vertex1;
|
TGroundVertex vertex, vertex0, vertex1;
|
||||||
std::size_t vertexcount{ 0 };
|
std::size_t vertexcount{ 0 };
|
||||||
@@ -1455,15 +1485,25 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
|
|||||||
importedvertices.pop_back();
|
importedvertices.pop_back();
|
||||||
}
|
}
|
||||||
tmp->iType = GL_LINES;
|
tmp->iType = GL_LINES;
|
||||||
|
tmp->Piece = new piece_node();
|
||||||
|
tmp->iNumPts = importedvertices.size();
|
||||||
|
|
||||||
auto const nv = importedvertices.size();
|
if( false == importedvertices.empty() ) {
|
||||||
tmp->Points = new glm::dvec3[ nv ];
|
|
||||||
tmp->iNumPts = nv;
|
tmp->Piece->vertices.swap( importedvertices );
|
||||||
for( std::size_t i = 0; i < nv; ++i ) {
|
|
||||||
tmp->Points[ i ] = importedvertices[ i ].position;
|
glm::dvec3 minpoint( std::numeric_limits<double>::max(), 0.0, std::numeric_limits<double>::max() );
|
||||||
tmp->pCenter += importedvertices[ i ].position;
|
glm::dvec3 maxpoint( std::numeric_limits<double>::lowest(), 0.0, std::numeric_limits<double>::lowest() );
|
||||||
|
for( auto const &vertex : tmp->Piece->vertices ) {
|
||||||
|
tmp->pCenter += vertex.position;
|
||||||
|
minpoint.x = std::min( minpoint.x, vertex.position.x );
|
||||||
|
minpoint.z = std::min( minpoint.z, vertex.position.z );
|
||||||
|
maxpoint.x = std::max( maxpoint.x, vertex.position.x );
|
||||||
|
maxpoint.z = std::max( maxpoint.z, vertex.position.z );
|
||||||
|
}
|
||||||
|
tmp->pCenter /= tmp->iNumPts;
|
||||||
|
tmp->m_radius = static_cast<float>( glm::distance( maxpoint, minpoint ) * 0.5 );
|
||||||
}
|
}
|
||||||
tmp->pCenter /= ( nv > 0 ? nv : 1 );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1559,11 +1599,6 @@ void TGround::FirstInit()
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// dodajemy do kwadratu kilometrowego
|
// 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 );
|
GetRect( Current->pCenter.x, Current->pCenter.z )->NodeAdd( Current );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1632,7 +1667,7 @@ bool TGround::Init(std::string File)
|
|||||||
switch( LastNode->iType ) {
|
switch( LastNode->iType ) {
|
||||||
// validate the new node
|
// validate the new node
|
||||||
case GL_TRIANGLES: {
|
case GL_TRIANGLES: {
|
||||||
if( LastNode->Vertices == nullptr ) {
|
if( true == LastNode->Piece->vertices.empty() ) {
|
||||||
SafeDelete( LastNode );
|
SafeDelete( LastNode );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1692,7 +1727,7 @@ bool TGround::Init(std::string File)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Error("Scene parse error near " + token);
|
ErrorLog("Scene parsing error in file \"" + parser.Name() + "\", unexpected token \"" + token + "\"");
|
||||||
// break;
|
// break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1722,20 +1757,21 @@ bool TGround::Init(std::string File)
|
|||||||
fTrainSetVel, 0, NULL);
|
fTrainSetVel, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LastNode) // ostatni wczytany obiekt
|
if( LastNode ) {
|
||||||
if (LastNode->iType ==
|
// ostatni wczytany obiekt
|
||||||
TP_DYNAMIC) // o ile jest pojazdem (na ogół jest, ale kto wie...)
|
if( LastNode->iType == TP_DYNAMIC ) {
|
||||||
if (iTrainSetWehicleNumber ? !TempConnectionType[iTrainSetWehicleNumber - 1] :
|
// o ile jest pojazdem (na ogół jest, ale kto wie...)
|
||||||
false) // jeśli ostatni pojazd ma sprzęg 0
|
if( ( iTrainSetWehicleNumber > 0 )
|
||||||
LastNode->DynamicObject->RaLightsSet(-1, 2 + 32 + 64); // to założymy mu
|
&& ( TempConnectionType[ iTrainSetWehicleNumber - 1 ] == 0 ) ) {
|
||||||
// końcówki blaszane
|
// jeśli ostatni pojazd ma sprzęg 0 to założymy mu końcówki blaszane
|
||||||
// (jak AI się
|
// (jak AI się odpali, to sobie poprawi)
|
||||||
// odpali, to sobie
|
LastNode->DynamicObject->RaLightsSet( -1, 2 + 32 + 64 );
|
||||||
// poprawi)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
bTrainSet = false;
|
bTrainSet = false;
|
||||||
fTrainSetVel = 0;
|
fTrainSetVel = 0;
|
||||||
// iTrainSetConnection=0;
|
nTrainSetNode = nTrainSetDriver = nullptr;
|
||||||
nTrainSetNode = nTrainSetDriver = NULL;
|
|
||||||
iTrainSetWehicleNumber = 0;
|
iTrainSetWehicleNumber = 0;
|
||||||
}
|
}
|
||||||
else if (str == "event")
|
else if (str == "event")
|
||||||
|
|||||||
45
Ground.h
45
Ground.h
@@ -93,15 +93,15 @@ struct TGroundVertex
|
|||||||
texture = interpolate( v1.texture, v2.texture, static_cast<float>( factor ) );
|
texture = interpolate( v1.texture, v2.texture, static_cast<float>( factor ) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
// ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node
|
// ground node holding single, unique piece of 3d geometry. TBD, TODO: unify this with basic 3d model node
|
||||||
struct mesh_node {
|
struct piece_node {
|
||||||
std::vector<TGroundVertex> vertices;
|
std::vector<TGroundVertex> vertices;
|
||||||
geometry_handle geometry; // geometry prepared for drawing
|
geometry_handle geometry { 0,0 }; // geometry prepared for drawing
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
class TGroundNode /*: public Resource*/
|
// obiekt scenerii
|
||||||
{ // obiekt scenerii
|
class TGroundNode {
|
||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
|
|
||||||
@@ -117,9 +117,8 @@ public:
|
|||||||
TSubModel *smTerrain; // modele terenu (kwadratow kilometrowych)
|
TSubModel *smTerrain; // modele terenu (kwadratow kilometrowych)
|
||||||
TAnimModel *Model; // model z animacjami
|
TAnimModel *Model; // model z animacjami
|
||||||
TDynamicObject *DynamicObject; // pojazd
|
TDynamicObject *DynamicObject; // pojazd
|
||||||
glm::dvec3 *Points; // punkty dla linii
|
piece_node *Piece; // non-instanced piece of geometry
|
||||||
TTrack *pTrack; // trajektoria ruchu
|
TTrack *pTrack; // trajektoria ruchu
|
||||||
TGroundVertex *Vertices; // wierzchołki dla trójkątów
|
|
||||||
TMemCell *MemCell; // komórka pamięci
|
TMemCell *MemCell; // komórka pamięci
|
||||||
TEventLauncher *EvLaunch; // wyzwalacz zdarzeń
|
TEventLauncher *EvLaunch; // wyzwalacz zdarzeń
|
||||||
TTraction *hvTraction; // drut zasilający
|
TTraction *hvTraction; // drut zasilający
|
||||||
@@ -128,6 +127,7 @@ public:
|
|||||||
TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
|
TGroundNode *nNode; // obiekt renderujący grupowo ma tu wskaźnik na listę obiektów
|
||||||
};
|
};
|
||||||
Math3D::vector3 pCenter; // współrzędne środka do przydzielenia sektora
|
Math3D::vector3 pCenter; // współrzędne środka do przydzielenia sektora
|
||||||
|
float m_radius { 0.0f }; // bounding radius of geometry stored in the node. TODO: reuse bounding_area struct for radius and center
|
||||||
glm::dvec3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
|
glm::dvec3 m_rootposition; // position of the ground (sub)rectangle holding the node, in the 3d world
|
||||||
// visualization-related data
|
// visualization-related data
|
||||||
// TODO: wrap these in a struct, when cleaning objects up
|
// TODO: wrap these in a struct, when cleaning objects up
|
||||||
@@ -139,9 +139,6 @@ public:
|
|||||||
int iNumPts; // dla linii
|
int iNumPts; // dla linii
|
||||||
int iCount; // dla terenu
|
int iCount; // dla terenu
|
||||||
};
|
};
|
||||||
// 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
|
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
|
||||||
texture_handle TextureID; // główna (jedna) tekstura obiektu
|
texture_handle TextureID; // główna (jedna) tekstura obiektu
|
||||||
glm::vec3
|
glm::vec3
|
||||||
@@ -152,9 +149,11 @@ public:
|
|||||||
bool bVisible;
|
bool bVisible;
|
||||||
|
|
||||||
TGroundNode();
|
TGroundNode();
|
||||||
TGroundNode(TGroundNodeType t, int n = 0);
|
TGroundNode(TGroundNodeType t);
|
||||||
~TGroundNode();
|
~TGroundNode();
|
||||||
|
/*
|
||||||
void Init(int n);
|
void Init(int n);
|
||||||
|
*/
|
||||||
void InitNormals();
|
void InitNormals();
|
||||||
/*
|
/*
|
||||||
void Release();
|
void Release();
|
||||||
@@ -200,7 +199,7 @@ class TSubRect : /*public Resource,*/ public CMesh
|
|||||||
/*
|
/*
|
||||||
virtual void Release(); // zwalnianie VBO sektora
|
virtual void Release(); // zwalnianie VBO sektora
|
||||||
*/
|
*/
|
||||||
void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
virtual void NodeAdd(TGroundNode *Node); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
||||||
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
|
void Sort(); // optymalizacja obiektów w sektorze (sortowanie wg tekstur)
|
||||||
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
|
TTrack * FindTrack(vector3 *Point, int &iConnection, TTrack *Exclude);
|
||||||
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
|
TTraction * FindTraction(glm::dvec3 const &Point, int &iConnection, TTraction *Exclude);
|
||||||
@@ -242,17 +241,19 @@ public:
|
|||||||
};
|
};
|
||||||
// pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
|
// pobranie wskaźnika do małego kwadratu, bez tworzenia jeśli nie ma
|
||||||
TSubRect * FastGetSubRect(int iCol, int iRow) {
|
TSubRect * FastGetSubRect(int iCol, int iRow) {
|
||||||
return (pSubRects ? pSubRects + iRow * iNumSubRects + iCol : NULL);
|
return (
|
||||||
};
|
pSubRects ?
|
||||||
|
pSubRects + iRow * iNumSubRects + iCol :
|
||||||
|
nullptr); };
|
||||||
|
void NodeAdd( TGroundNode *Node ); // dodanie obiektu do sektora na etapie rozdzielania na sektory
|
||||||
|
// compares two provided nodes, returns true if their content can be merged
|
||||||
|
bool mergeable( TGroundNode const &Left, TGroundNode const &Right );
|
||||||
// optymalizacja obiektów w sektorach
|
// optymalizacja obiektów w sektorach
|
||||||
void Optimize() {
|
void Optimize() {
|
||||||
if( pSubRects ) {
|
if( pSubRects ) {
|
||||||
for( int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i ) {
|
for( int i = iNumSubRects * iNumSubRects - 1; i >= 0; --i ) {
|
||||||
// optymalizacja obiektów w sektorach
|
// optymalizacja obiektów w sektorach
|
||||||
pSubRects[ i ].Sort();
|
pSubRects[ i ].Sort(); } } };
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int iFrameNumber; // numer kolejny wyświetlanej klatki
|
static int iFrameNumber; // numer kolejny wyświetlanej klatki
|
||||||
TGroundNode *nTerrain { nullptr }; // model terenu z E3D - użyć nRootMesh?
|
TGroundNode *nTerrain { nullptr }; // model terenu z E3D - użyć nRootMesh?
|
||||||
@@ -308,8 +309,8 @@ class TGround
|
|||||||
bool AddToQuery(TEvent *Event, TDynamicObject *Node);
|
bool AddToQuery(TEvent *Event, TDynamicObject *Node);
|
||||||
bool GetTraction(TDynamicObject *model);
|
bool GetTraction(TDynamicObject *model);
|
||||||
bool CheckQuery();
|
bool CheckQuery();
|
||||||
TGroundNode * DynamicFindAny(std::string asNameToFind);
|
TGroundNode * DynamicFindAny(std::string const &Name);
|
||||||
TGroundNode * DynamicFind(std::string asNameToFind);
|
TGroundNode * DynamicFind(std::string const &Name);
|
||||||
void DynamicList(bool all = false);
|
void DynamicList(bool all = false);
|
||||||
TGroundNode * FindGroundNode(std::string asNameToFind, TGroundNodeType iNodeType);
|
TGroundNode * FindGroundNode(std::string asNameToFind, TGroundNodeType iNodeType);
|
||||||
TGroundRect * GetRect(double x, double z)
|
TGroundRect * GetRect(double x, double z)
|
||||||
@@ -343,7 +344,9 @@ class TGround
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void WyslijEvent(const std::string &e, const std::string &d);
|
void WyslijEvent(const std::string &e, const std::string &d);
|
||||||
|
/*
|
||||||
int iRendered; // ilość renderowanych sektorów, pobierana przy pokazywniu FPS
|
int iRendered; // ilość renderowanych sektorów, pobierana przy pokazywniu FPS
|
||||||
|
*/
|
||||||
void WyslijString(const std::string &t, int n);
|
void WyslijString(const std::string &t, int n);
|
||||||
void WyslijWolny(const std::string &t);
|
void WyslijWolny(const std::string &t);
|
||||||
void WyslijNamiary(TGroundNode *t);
|
void WyslijNamiary(TGroundNode *t);
|
||||||
|
|||||||
30
Model3d.cpp
30
Model3d.cpp
@@ -78,6 +78,23 @@ void TSubModel::NameSet(std::string const &Name)
|
|||||||
pName = Name;
|
pName = Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// sets light level (alpha component of illumination color) to specified value
|
||||||
|
void
|
||||||
|
TSubModel::SetLightLevel( float const Level, bool const Includechildren, bool const Includesiblings ) {
|
||||||
|
|
||||||
|
f4Emision.a = Level;
|
||||||
|
if( true == Includesiblings ) {
|
||||||
|
auto sibling { this };
|
||||||
|
while( ( sibling = sibling->Next ) != nullptr ) {
|
||||||
|
sibling->f4Emision.a = Level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( true == Includechildren )
|
||||||
|
&& ( Child != nullptr ) ) {
|
||||||
|
Child->SetLightLevel( Level, true, true ); // node's children include child's siblings and children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -315,9 +332,9 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // jeśli tylko nazwa pliku, to dawać bieżącą ścieżkę do tekstur
|
{ // jeśli tylko nazwa pliku, to dawać bieżącą ścieżkę do tekstur
|
||||||
TextureNameSet(texture.c_str());
|
TextureNameSet(texture);
|
||||||
if( texture.find_first_of( "/\\" ) == texture.npos ) {
|
if( texture.find_first_of( "/\\" ) == texture.npos ) {
|
||||||
texture.insert( 0, Global::asCurrentTexturePath.c_str() );
|
texture.insert( 0, Global::asCurrentTexturePath );
|
||||||
}
|
}
|
||||||
TextureID = GfxRenderer.GetTextureId( texture, szTexturePath );
|
TextureID = GfxRenderer.GetTextureId( texture, szTexturePath );
|
||||||
// renderowanie w cyklu przezroczystych tylko jeśli:
|
// renderowanie w cyklu przezroczystych tylko jeśli:
|
||||||
@@ -429,7 +446,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
|||||||
--facecount; // o jeden trójkąt mniej
|
--facecount; // o jeden trójkąt mniej
|
||||||
iNumVerts -= 3; // czyli o 3 wierzchołki
|
iNumVerts -= 3; // czyli o 3 wierzchołki
|
||||||
i -= 3; // wczytanie kolejnego w to miejsce
|
i -= 3; // wczytanie kolejnego w to miejsce
|
||||||
WriteLog("Degenerated triangle ignored in: \"" + pName + "\", verticle " + std::to_string(i));
|
WriteLog("Degenerated triangle ignored in: \"" + pName + "\", vertice " + std::to_string(i));
|
||||||
}
|
}
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
// jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać
|
// jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać
|
||||||
@@ -487,6 +504,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
|||||||
glm::vec3() ); // przepisanie do wierzchołka trójkąta
|
glm::vec3() ); // przepisanie do wierzchołka trójkąta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Vertices.resize( iNumVerts ); // in case we had some degenerate triangles along the way
|
||||||
/*
|
/*
|
||||||
delete[] wsp;
|
delete[] wsp;
|
||||||
delete[] n;
|
delete[] n;
|
||||||
@@ -534,6 +552,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
|||||||
else if( eType == TP_FREESPOTLIGHT ) {
|
else if( eType == TP_FREESPOTLIGHT ) {
|
||||||
// single light points only have single data point, duh
|
// single light points only have single data point, duh
|
||||||
Vertices.emplace_back();
|
Vertices.emplace_back();
|
||||||
|
iNumVerts = 1;
|
||||||
}
|
}
|
||||||
// Visible=true; //się potem wyłączy w razie potrzeby
|
// Visible=true; //się potem wyłączy w razie potrzeby
|
||||||
// iFlags|=0x0200; //wczytano z pliku tekstowego (jest właścicielem tablic)
|
// iFlags|=0x0200; //wczytano z pliku tekstowego (jest właścicielem tablic)
|
||||||
@@ -711,10 +730,6 @@ void TSubModel::InitialRotate(bool doit)
|
|||||||
{ // jeśli jest jednostkowy transform, to przeliczamy
|
{ // jeśli jest jednostkowy transform, to przeliczamy
|
||||||
// wierzchołki, a mnożenie podajemy dalej
|
// wierzchołki, a mnożenie podajemy dalej
|
||||||
float swapcopy;
|
float swapcopy;
|
||||||
// if( false == Vertices.empty() ) {
|
|
||||||
/*
|
|
||||||
for( auto &vertex : Vertices ) {
|
|
||||||
*/
|
|
||||||
for( auto &vertex : Vertices ) {
|
for( auto &vertex : Vertices ) {
|
||||||
vertex.position.x = -vertex.position.x; // zmiana znaku X
|
vertex.position.x = -vertex.position.x; // zmiana znaku X
|
||||||
swapcopy = vertex.position.y; // zamiana Y i Z
|
swapcopy = vertex.position.y; // zamiana Y i Z
|
||||||
@@ -729,7 +744,6 @@ void TSubModel::InitialRotate(bool doit)
|
|||||||
vertex.normal.z = swapcopy;
|
vertex.normal.z = swapcopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
if (Child)
|
if (Child)
|
||||||
Child->InitialRotate(doit); // potomne ewentualnie obrócimy
|
Child->InitialRotate(doit); // potomne ewentualnie obrócimy
|
||||||
}
|
}
|
||||||
|
|||||||
27
Model3d.h
27
Model3d.h
@@ -56,6 +56,7 @@ class TSubModel
|
|||||||
|
|
||||||
friend class opengl_renderer;
|
friend class opengl_renderer;
|
||||||
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
friend class TModel3d; // temporary workaround. TODO: clean up class content/hierarchy
|
||||||
|
friend class TDynamicObject; // temporary etc
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int iNext{ NULL };
|
int iNext{ NULL };
|
||||||
@@ -110,15 +111,9 @@ private:
|
|||||||
|
|
||||||
TSubModel *Next { nullptr };
|
TSubModel *Next { nullptr };
|
||||||
TSubModel *Child { nullptr };
|
TSubModel *Child { nullptr };
|
||||||
/*
|
|
||||||
intptr_t iVboPtr;
|
|
||||||
*/
|
|
||||||
geometry_handle m_geometry { NULL, NULL }; // geometry of the submodel
|
geometry_handle m_geometry { NULL, NULL }; // geometry of the submodel
|
||||||
texture_handle TextureID { NULL }; // numer tekstury, -1 wymienna, 0 brak
|
texture_handle TextureID { NULL }; // numer tekstury, -1 wymienna, 0 brak
|
||||||
bool bWire { false }; // nie używane, ale wczytywane
|
bool bWire { false }; // nie używane, ale wczytywane
|
||||||
/*
|
|
||||||
GLuint uiDisplayList; // roboczy numer listy wyświetlania
|
|
||||||
*/
|
|
||||||
float Opacity { 1.0f };
|
float Opacity { 1.0f };
|
||||||
float f_Angle { 0.0f };
|
float f_Angle { 0.0f };
|
||||||
float3 v_RotateAxis { 0.0f, 0.0f, 0.0f };
|
float3 v_RotateAxis { 0.0f, 0.0f, 0.0f };
|
||||||
@@ -192,18 +187,14 @@ public:
|
|||||||
int Flags() { return iFlags; };
|
int Flags() { return iFlags; };
|
||||||
void UnFlagNext() { iFlags &= 0x00FFFFFF; };
|
void UnFlagNext() { iFlags &= 0x00FFFFFF; };
|
||||||
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
|
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
|
||||||
inline float3 Translation1Get()
|
// sets light level (alpha component of illumination color) to specified value
|
||||||
{
|
void SetLightLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false );
|
||||||
return fMatrix ? *(fMatrix->TranslationGet()) + v_TransVector : v_TransVector;
|
inline float3 Translation1Get() {
|
||||||
}
|
return fMatrix ? *(fMatrix->TranslationGet()) + v_TransVector : v_TransVector; }
|
||||||
inline float3 Translation2Get()
|
inline float3 Translation2Get() {
|
||||||
{
|
return *(fMatrix->TranslationGet()) + Child->Translation1Get(); }
|
||||||
return *(fMatrix->TranslationGet()) + Child->Translation1Get();
|
int GetTextureId() {
|
||||||
}
|
return TextureID; }
|
||||||
int GetTextureId()
|
|
||||||
{
|
|
||||||
return TextureID;
|
|
||||||
}
|
|
||||||
void ParentMatrix(float4x4 *m);
|
void ParentMatrix(float4x4 *m);
|
||||||
float MaxY( float4x4 const &m );
|
float MaxY( float4x4 const &m );
|
||||||
void AdjustDist();
|
void AdjustDist();
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ void TPythonScreens::init(cParser &parser, TModel3d *model, std::string const &n
|
|||||||
WriteLog( "Python Screen: submodel " + subModelName + " not found - Ignoring screen" );
|
WriteLog( "Python Screen: submodel " + subModelName + " not found - Ignoring screen" );
|
||||||
return; // nie ma takiego sub modelu w danej kabinie pomijamy
|
return; // nie ma takiego sub modelu w danej kabinie pomijamy
|
||||||
}
|
}
|
||||||
int textureId = GfxRenderer.Texture(subModel->GetTextureId()).id;
|
auto textureId = subModel->GetTextureId();
|
||||||
if (textureId <= 0)
|
if (textureId <= 0)
|
||||||
{
|
{
|
||||||
WriteLog( "Python Screen: invalid texture id " + std::to_string(textureId) + " - Ignoring screen" );
|
WriteLog( "Python Screen: invalid texture id " + std::to_string(textureId) + " - Ignoring screen" );
|
||||||
|
|||||||
@@ -817,8 +817,8 @@ texture_manager::bind( texture_handle const Texture ) {
|
|||||||
::glBindTexture( GL_TEXTURE_2D, texture(Texture).id );
|
::glBindTexture( GL_TEXTURE_2D, texture(Texture).id );
|
||||||
m_activetexture = texture(Texture).id;
|
m_activetexture = texture(Texture).id;
|
||||||
#else
|
#else
|
||||||
if( Texture( Id ).bind() == resource_state::good ) {
|
if( texture( Texture ).bind() == resource_state::good ) {
|
||||||
m_activetexture = Id;
|
m_activetexture = Texture;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: bind a special 'error' texture on failure
|
// TODO: bind a special 'error' texture on failure
|
||||||
@@ -876,7 +876,7 @@ texture_manager::info() const {
|
|||||||
+ std::to_string( readytexturecount )
|
+ std::to_string( readytexturecount )
|
||||||
+ " ("
|
+ " ("
|
||||||
+ to_string( readytexturesize / 1024.0f, 2 ) + " mb)"
|
+ to_string( readytexturesize / 1024.0f, 2 ) + " mb)"
|
||||||
+ " in vram, ";
|
+ " in vram, "
|
||||||
#endif
|
#endif
|
||||||
+ std::to_string( totaltexturecount )
|
+ std::to_string( totaltexturecount )
|
||||||
+ " ("
|
+ " ("
|
||||||
|
|||||||
14
Texture.h
14
Texture.h
@@ -29,8 +29,18 @@ struct opengl_texture {
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
void load();
|
void load();
|
||||||
resource_state bind();
|
resource_state
|
||||||
resource_state create();
|
bind();
|
||||||
|
resource_state
|
||||||
|
create();
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
width() const {
|
||||||
|
return data_width; }
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
height() const {
|
||||||
|
return data_height; }
|
||||||
// members
|
// members
|
||||||
GLuint id{ (GLuint)-1 }; // associated GL resource
|
GLuint id{ (GLuint)-1 }; // associated GL resource
|
||||||
bool has_alpha{ false }; // indicates the texture has alpha channel
|
bool has_alpha{ false }; // indicates the texture has alpha channel
|
||||||
|
|||||||
@@ -2156,7 +2156,6 @@ TTrack * TTrack::RaAnimate()
|
|||||||
|
|
||||||
if (SwitchExtension->RightSwitch)
|
if (SwitchExtension->RightSwitch)
|
||||||
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
|
||||||
vertex_array vertices;
|
|
||||||
if( TextureID1 ) {
|
if( TextureID1 ) {
|
||||||
// left blade
|
// left blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
|
||||||
@@ -2171,7 +2170,6 @@ TTrack * TTrack::RaAnimate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // lewa działa lepiej niż prawa
|
else { // lewa działa lepiej niż prawa
|
||||||
vertex_array vertices;
|
|
||||||
if( TextureID1 ) {
|
if( TextureID1 ) {
|
||||||
// right blade
|
// right blade
|
||||||
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
|
||||||
|
|||||||
@@ -5889,9 +5889,8 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
//światło wewnętrzne zapalone (255 216 176)
|
//światło wewnętrzne zapalone (255 216 176)
|
||||||
if( mvOccupied->ConverterFlag ==
|
if( mvOccupied->ConverterFlag == true ) {
|
||||||
true ) // jasnosc dla zalaczonej przetwornicy
|
// jasnosc dla zalaczonej przetwornicy
|
||||||
{
|
|
||||||
DynamicObject->InteriorLightLevel = 1.0f;
|
DynamicObject->InteriorLightLevel = 1.0f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -6441,6 +6440,10 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|||||||
{
|
{
|
||||||
DynamicObject->mdKabina->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego
|
DynamicObject->mdKabina->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego
|
||||||
set_cab_controls();
|
set_cab_controls();
|
||||||
|
// HACK: for some reason simulation at the start is slow until a sound is played
|
||||||
|
// until we do a proper fix, try to play a 'silent' sound when cab is entered
|
||||||
|
// TBD: it could be instead a legit sound of door closing
|
||||||
|
play_sound( dsbSwitch, DSBVOLUME_MIN );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (token == "none");
|
return (token == "none");
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ geometry_bank::create( vertex_array &Vertices, unsigned int const Type ) {
|
|||||||
m_chunks.emplace_back( Vertices, Type );
|
m_chunks.emplace_back( Vertices, Type );
|
||||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
// 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, static_cast<std::uint32_t>(m_chunks.size()) };
|
geometry_handle chunkhandle { 0, static_cast<std::uint32_t>(m_chunks.size()) };
|
||||||
// template method
|
// template method implementation
|
||||||
create_( chunkhandle );
|
create_( chunkhandle );
|
||||||
// all done
|
// all done
|
||||||
return chunkhandle;
|
return chunkhandle;
|
||||||
@@ -81,7 +81,7 @@ geometry_bank::replace( vertex_array &Vertices, geometry_handle const &Geometry,
|
|||||||
chunk.vertices.resize( Offset + Vertices.size(), basic_vertex() );
|
chunk.vertices.resize( Offset + Vertices.size(), basic_vertex() );
|
||||||
chunk.vertices.insert( std::end( chunk.vertices ), std::begin( Vertices ), std::end( Vertices ) );
|
chunk.vertices.insert( std::end( chunk.vertices ), std::begin( Vertices ), std::end( Vertices ) );
|
||||||
}
|
}
|
||||||
// template method
|
// template method implementation
|
||||||
replace_( Geometry );
|
replace_( Geometry );
|
||||||
// all done
|
// all done
|
||||||
return true;
|
return true;
|
||||||
@@ -99,10 +99,17 @@ geometry_bank::append( vertex_array &Vertices, geometry_handle const &Geometry )
|
|||||||
// draws geometry stored in specified chunk
|
// draws geometry stored in specified chunk
|
||||||
void
|
void
|
||||||
geometry_bank::draw( geometry_handle const &Geometry, unsigned int const Streams ) {
|
geometry_bank::draw( geometry_handle const &Geometry, unsigned int const Streams ) {
|
||||||
// template method
|
// template method implementation
|
||||||
draw_( Geometry, Streams );
|
draw_( Geometry, Streams );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// frees subclass-specific resources associated with the bank, typically called when the bank wasn't in use for a period of time
|
||||||
|
void
|
||||||
|
geometry_bank::release() {
|
||||||
|
// template method implementation
|
||||||
|
release_();
|
||||||
|
}
|
||||||
|
|
||||||
vertex_array const &
|
vertex_array const &
|
||||||
geometry_bank::vertices( geometry_handle const &Geometry ) const {
|
geometry_bank::vertices( geometry_handle const &Geometry ) const {
|
||||||
|
|
||||||
@@ -209,6 +216,13 @@ opengl_vbogeometrybank::draw_( geometry_handle const &Geometry, unsigned int con
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// release () subclass details
|
||||||
|
void
|
||||||
|
opengl_vbogeometrybank::release_() {
|
||||||
|
|
||||||
|
delete_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
opengl_vbogeometrybank::bind_buffer() {
|
opengl_vbogeometrybank::bind_buffer() {
|
||||||
|
|
||||||
@@ -225,6 +239,7 @@ opengl_vbogeometrybank::delete_buffer() {
|
|||||||
::glDeleteBuffers( 1, &m_buffer );
|
::glDeleteBuffers( 1, &m_buffer );
|
||||||
if( m_activebuffer == m_buffer ) {
|
if( m_activebuffer == m_buffer ) {
|
||||||
m_activebuffer = NULL;
|
m_activebuffer = NULL;
|
||||||
|
bind_streams( stream::none );
|
||||||
}
|
}
|
||||||
m_buffer = NULL;
|
m_buffer = NULL;
|
||||||
m_buffercapacity = 0;
|
m_buffercapacity = 0;
|
||||||
@@ -314,6 +329,19 @@ opengl_dlgeometrybank::draw_( geometry_handle const &Geometry, unsigned int cons
|
|||||||
::glCallList( chunkrecord.list );
|
::glCallList( chunkrecord.list );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// release () subclass details
|
||||||
|
void
|
||||||
|
opengl_dlgeometrybank::release_() {
|
||||||
|
|
||||||
|
for( auto &chunkrecord : m_chunkrecords ) {
|
||||||
|
if( chunkrecord.list != 0 ) {
|
||||||
|
::glDeleteLists( chunkrecord.list, 1 );
|
||||||
|
chunkrecord.list = 0;
|
||||||
|
}
|
||||||
|
chunkrecord.streams = stream::none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
opengl_dlgeometrybank::delete_list( geometry_handle const &Geometry ) {
|
opengl_dlgeometrybank::delete_list( geometry_handle const &Geometry ) {
|
||||||
// NOTE: given it's our own internal method we trust it to be called with valid parameters
|
// NOTE: given it's our own internal method we trust it to be called with valid parameters
|
||||||
@@ -327,12 +355,37 @@ opengl_dlgeometrybank::delete_list( geometry_handle const &Geometry ) {
|
|||||||
|
|
||||||
// geometry bank manager, holds collection of geometry banks
|
// geometry bank manager, holds collection of geometry banks
|
||||||
|
|
||||||
|
// performs a resource sweep
|
||||||
|
void
|
||||||
|
geometrybank_manager::update() {
|
||||||
|
|
||||||
|
m_resourcetimestamp = std::chrono::steady_clock::now();
|
||||||
|
// garbage collection sweep is limited to a number of records per call, to reduce impact on framerate
|
||||||
|
auto const sweeplastindex =
|
||||||
|
std::min(
|
||||||
|
m_resourcesweepindex + geometrybank_manager::unusedresourcesweepsize,
|
||||||
|
m_geometrybanks.size() );
|
||||||
|
auto const blanktimestamp { std::chrono::steady_clock::time_point() };
|
||||||
|
for( auto bankindex = m_resourcesweepindex; bankindex < sweeplastindex; ++bankindex ) {
|
||||||
|
if( ( m_geometrybanks[ bankindex ].second != blanktimestamp )
|
||||||
|
&& ( m_resourcetimestamp - m_geometrybanks[ bankindex ].second > geometrybank_manager::unusedresourcetimetolive ) ) {
|
||||||
|
|
||||||
|
m_geometrybanks[ bankindex ].first->release();
|
||||||
|
m_geometrybanks[ bankindex ].second = blanktimestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_resourcesweepindex = (
|
||||||
|
m_resourcesweepindex + geometrybank_manager::unusedresourcesweepsize >= m_geometrybanks.size() ?
|
||||||
|
0 : // if the next sweep chunk is beyond actual data, so start anew
|
||||||
|
m_resourcesweepindex + geometrybank_manager::unusedresourcesweepsize );
|
||||||
|
}
|
||||||
|
|
||||||
// creates a new geometry bank. returns: handle to the bank or NULL
|
// creates a new geometry bank. returns: handle to the bank or NULL
|
||||||
geometrybank_handle
|
geometrybank_handle
|
||||||
geometrybank_manager::create_bank() {
|
geometrybank_manager::create_bank() {
|
||||||
|
|
||||||
if( true == Global::bUseVBO ) { m_geometrybanks.emplace_back( std::make_shared<opengl_vbogeometrybank>() ); }
|
if( true == Global::bUseVBO ) { m_geometrybanks.emplace_back( std::make_shared<opengl_vbogeometrybank>(), std::chrono::steady_clock::time_point() ); }
|
||||||
else { m_geometrybanks.emplace_back( std::make_shared<opengl_dlgeometrybank>() ); }
|
else { m_geometrybanks.emplace_back( std::make_shared<opengl_dlgeometrybank>(), std::chrono::steady_clock::time_point() ); }
|
||||||
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
|
||||||
return geometrybank_handle( m_geometrybanks.size(), 0 );
|
return geometrybank_handle( m_geometrybanks.size(), 0 );
|
||||||
}
|
}
|
||||||
@@ -341,7 +394,7 @@ geometrybank_manager::create_bank() {
|
|||||||
geometry_handle
|
geometry_handle
|
||||||
geometrybank_manager::create_chunk( vertex_array &Vertices, geometrybank_handle const &Geometry, int const Type ) {
|
geometrybank_manager::create_chunk( vertex_array &Vertices, geometrybank_handle const &Geometry, int const Type ) {
|
||||||
|
|
||||||
auto const newchunkhandle = bank( Geometry )->create( Vertices, Type );
|
auto const newchunkhandle = bank( Geometry ).first->create( Vertices, Type );
|
||||||
|
|
||||||
if( newchunkhandle.chunk != 0 ) { return geometry_handle( Geometry.bank, newchunkhandle.chunk ); }
|
if( newchunkhandle.chunk != 0 ) { return geometry_handle( Geometry.bank, newchunkhandle.chunk ); }
|
||||||
else { return geometry_handle( 0, 0 ); }
|
else { return geometry_handle( 0, 0 ); }
|
||||||
@@ -351,14 +404,14 @@ geometrybank_manager::create_chunk( vertex_array &Vertices, geometrybank_handle
|
|||||||
bool
|
bool
|
||||||
geometrybank_manager::replace( vertex_array &Vertices, geometry_handle const &Geometry, std::size_t const Offset ) {
|
geometrybank_manager::replace( vertex_array &Vertices, geometry_handle const &Geometry, std::size_t const Offset ) {
|
||||||
|
|
||||||
return bank( Geometry )->replace( Vertices, Geometry, Offset );
|
return bank( Geometry ).first->replace( Vertices, Geometry, Offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds supplied vertex data at the end of specified chunk
|
// adds supplied vertex data at the end of specified chunk
|
||||||
bool
|
bool
|
||||||
geometrybank_manager::append( vertex_array &Vertices, geometry_handle const &Geometry ) {
|
geometrybank_manager::append( vertex_array &Vertices, geometry_handle const &Geometry ) {
|
||||||
|
|
||||||
return bank( Geometry )->append( Vertices, Geometry );
|
return bank( Geometry ).first->append( Vertices, Geometry );
|
||||||
}
|
}
|
||||||
// draws geometry stored in specified chunk
|
// draws geometry stored in specified chunk
|
||||||
void
|
void
|
||||||
@@ -366,12 +419,15 @@ geometrybank_manager::draw( geometry_handle const &Geometry, unsigned int const
|
|||||||
|
|
||||||
if( Geometry == NULL ) { return; }
|
if( Geometry == NULL ) { return; }
|
||||||
|
|
||||||
return bank( Geometry )->draw( Geometry, Streams );
|
auto &bankrecord = bank( Geometry );
|
||||||
|
|
||||||
|
bankrecord.second = m_resourcetimestamp;
|
||||||
|
bankrecord.first->draw( Geometry, Streams );
|
||||||
}
|
}
|
||||||
|
|
||||||
// provides direct access to vertex data of specfied chunk
|
// provides direct access to vertex data of specfied chunk
|
||||||
vertex_array const &
|
vertex_array const &
|
||||||
geometrybank_manager::vertices( geometry_handle const &Geometry ) const {
|
geometrybank_manager::vertices( geometry_handle const &Geometry ) const {
|
||||||
|
|
||||||
return bank( Geometry )->vertices( Geometry );
|
return bank( Geometry ).first->vertices( Geometry );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ public:
|
|||||||
template <typename Iterator_>
|
template <typename Iterator_>
|
||||||
void
|
void
|
||||||
draw( Iterator_ First, Iterator_ Last, unsigned int const Streams = basic_streams ) { while( First != Last ) { draw( *First, Streams ); ++First; } }
|
draw( Iterator_ First, Iterator_ Last, unsigned int const Streams = basic_streams ) { while( First != Last ) { draw( *First, Streams ); ++First; } }
|
||||||
|
// frees subclass-specific resources associated with the bank, typically called when the bank wasn't in use for a period of time
|
||||||
|
void
|
||||||
|
release();
|
||||||
// provides direct access to vertex data of specfied chunk
|
// provides direct access to vertex data of specfied chunk
|
||||||
vertex_array const &
|
vertex_array const &
|
||||||
vertices( geometry_handle const &Geometry ) const;
|
vertices( geometry_handle const &Geometry ) const;
|
||||||
@@ -142,6 +145,8 @@ private:
|
|||||||
virtual void replace_( geometry_handle const &Geometry ) = 0;
|
virtual void replace_( geometry_handle const &Geometry ) = 0;
|
||||||
// draw() subclass details
|
// draw() subclass details
|
||||||
virtual void draw_( geometry_handle const &Geometry, unsigned int const Streams ) = 0;
|
virtual void draw_( geometry_handle const &Geometry, unsigned int const Streams ) = 0;
|
||||||
|
// resource release subclass details
|
||||||
|
virtual void release_() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// opengl vbo-based variant of the geometry bank
|
// opengl vbo-based variant of the geometry bank
|
||||||
@@ -149,6 +154,8 @@ private:
|
|||||||
class opengl_vbogeometrybank : public geometry_bank {
|
class opengl_vbogeometrybank : public geometry_bank {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// constructors:
|
||||||
|
opengl_vbogeometrybank() = default;
|
||||||
// destructor
|
// destructor
|
||||||
~opengl_vbogeometrybank() {
|
~opengl_vbogeometrybank() {
|
||||||
delete_buffer(); }
|
delete_buffer(); }
|
||||||
@@ -179,6 +186,9 @@ private:
|
|||||||
// draw() subclass details
|
// draw() subclass details
|
||||||
void
|
void
|
||||||
draw_( geometry_handle const &Geometry, unsigned int const Streams );
|
draw_( geometry_handle const &Geometry, unsigned int const Streams );
|
||||||
|
// release () subclass details
|
||||||
|
void
|
||||||
|
release_();
|
||||||
void
|
void
|
||||||
bind_buffer();
|
bind_buffer();
|
||||||
void
|
void
|
||||||
@@ -200,7 +210,9 @@ private:
|
|||||||
class opengl_dlgeometrybank : public geometry_bank {
|
class opengl_dlgeometrybank : public geometry_bank {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// methods:
|
// constructors:
|
||||||
|
opengl_dlgeometrybank() = default;
|
||||||
|
// destructor:
|
||||||
~opengl_dlgeometrybank() {
|
~opengl_dlgeometrybank() {
|
||||||
for( auto &chunkrecord : m_chunkrecords ) {
|
for( auto &chunkrecord : m_chunkrecords ) {
|
||||||
::glDeleteLists( chunkrecord.list, 1 ); } }
|
::glDeleteLists( chunkrecord.list, 1 ); } }
|
||||||
@@ -224,6 +236,9 @@ private:
|
|||||||
// draw() subclass details
|
// draw() subclass details
|
||||||
void
|
void
|
||||||
draw_( geometry_handle const &Geometry, unsigned int const Streams );
|
draw_( geometry_handle const &Geometry, unsigned int const Streams );
|
||||||
|
// release () subclass details
|
||||||
|
void
|
||||||
|
release_();
|
||||||
void
|
void
|
||||||
delete_list( geometry_handle const &Geometry );
|
delete_list( geometry_handle const &Geometry );
|
||||||
|
|
||||||
@@ -240,6 +255,8 @@ class geometrybank_manager {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// methods:
|
// methods:
|
||||||
|
// performs a resource sweep
|
||||||
|
void update();
|
||||||
// creates a new geometry bank. returns: handle to the bank or NULL
|
// creates a new geometry bank. returns: handle to the bank or NULL
|
||||||
geometrybank_handle
|
geometrybank_handle
|
||||||
create_bank();
|
create_bank();
|
||||||
@@ -267,10 +284,18 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// types:
|
// types:
|
||||||
typedef std::deque< std::shared_ptr<geometry_bank> > geometrybank_sequence;
|
typedef std::pair<
|
||||||
|
std::shared_ptr<geometry_bank>,
|
||||||
|
std::chrono::steady_clock::time_point > geometrybanktimepoint_pair;
|
||||||
|
|
||||||
|
typedef std::deque< geometrybanktimepoint_pair > geometrybanktimepointpair_sequence;
|
||||||
|
|
||||||
// members:
|
// members:
|
||||||
geometrybank_sequence m_geometrybanks;
|
std::chrono::nanoseconds const unusedresourcetimetolive { std::chrono::seconds { 60 } };
|
||||||
|
geometrybanktimepointpair_sequence::size_type const unusedresourcesweepsize { 300 };
|
||||||
|
geometrybanktimepointpair_sequence m_geometrybanks;
|
||||||
|
geometrybanktimepointpair_sequence::size_type m_resourcesweepindex { 0 };
|
||||||
|
std::chrono::steady_clock::time_point m_resourcetimestamp { std::chrono::steady_clock::now() };
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
inline
|
inline
|
||||||
@@ -279,11 +304,11 @@ private:
|
|||||||
return ( ( Geometry.bank != 0 )
|
return ( ( Geometry.bank != 0 )
|
||||||
&& ( Geometry.bank <= m_geometrybanks.size() ) ); }
|
&& ( Geometry.bank <= m_geometrybanks.size() ) ); }
|
||||||
inline
|
inline
|
||||||
geometrybank_sequence::value_type &
|
geometrybanktimepointpair_sequence::value_type &
|
||||||
bank( geometry_handle const Geometry ) {
|
bank( geometry_handle const Geometry ) {
|
||||||
return m_geometrybanks[ Geometry.bank - 1 ]; }
|
return m_geometrybanks[ Geometry.bank - 1 ]; }
|
||||||
inline
|
inline
|
||||||
geometrybank_sequence::value_type const &
|
geometrybanktimepointpair_sequence::value_type const &
|
||||||
bank( geometry_handle const Geometry ) const {
|
bank( geometry_handle const Geometry ) const {
|
||||||
return m_geometrybanks[ Geometry.bank - 1 ]; }
|
return m_geometrybanks[ Geometry.bank - 1 ]; }
|
||||||
|
|
||||||
|
|||||||
17
parser.cpp
17
parser.cpp
@@ -201,14 +201,19 @@ std::string cParser::readQuotes(char const Quote) { // read the stream until spe
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cParser::readComment( std::string const &Break ) { // pobieranie znaków aż do znalezienia znacznika końca
|
void cParser::skipComment( std::string const &Endmark ) { // pobieranie znaków aż do znalezienia znacznika końca
|
||||||
std::string token = "";
|
std::string input = "";
|
||||||
|
auto const endmarksize = Endmark.size();
|
||||||
while( mStream->peek() != EOF ) { // o ile nie koniec pliku
|
while( mStream->peek() != EOF ) { // o ile nie koniec pliku
|
||||||
token += mStream->get(); // pobranie znaku
|
input += mStream->get(); // pobranie znaku
|
||||||
if( token.rfind( Break ) != std::string::npos ) // szukanie znacznika końca
|
if( input.find( Endmark ) != std::string::npos ) // szukanie znacznika końca
|
||||||
break;
|
break;
|
||||||
|
if( input.size() >= endmarksize ) {
|
||||||
|
// keep the read text short, to avoid pointless string re-allocations on longer comments
|
||||||
|
input = input.substr( 1 );
|
||||||
}
|
}
|
||||||
return token;
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cParser::findQuotes( std::string &String ) {
|
bool cParser::findQuotes( std::string &String ) {
|
||||||
@@ -228,7 +233,7 @@ bool cParser::trimComments(std::string &String)
|
|||||||
{
|
{
|
||||||
if (String.rfind((*cmIt).first) != std::string::npos)
|
if (String.rfind((*cmIt).first) != std::string::npos)
|
||||||
{
|
{
|
||||||
readComment((*cmIt).second);
|
skipComment((*cmIt).second);
|
||||||
String.resize(String.rfind((*cmIt).first));
|
String.resize(String.rfind((*cmIt).first));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
2
parser.h
2
parser.h
@@ -92,7 +92,7 @@ class cParser //: public std::stringstream
|
|||||||
// methods:
|
// methods:
|
||||||
std::string readToken(bool ToLower = true, const char *Break = "\n\r\t ;");
|
std::string readToken(bool ToLower = true, const char *Break = "\n\r\t ;");
|
||||||
std::string readQuotes( char const Quote = '\"' );
|
std::string readQuotes( char const Quote = '\"' );
|
||||||
std::string readComment( std::string const &Break = "\n\r\t ;" );
|
void skipComment( std::string const &Endmark );
|
||||||
bool findQuotes( std::string &String );
|
bool findQuotes( std::string &String );
|
||||||
bool trimComments( std::string &String );
|
bool trimComments( std::string &String );
|
||||||
std::size_t count();
|
std::size_t count();
|
||||||
|
|||||||
65
renderer.cpp
65
renderer.cpp
@@ -157,6 +157,7 @@ opengl_renderer::Render() {
|
|||||||
// frustum tests are performed in 'world space' but after we set up frustum
|
// frustum tests are performed in 'world space' but after we set up frustum
|
||||||
// we no longer need camera translation, only rotation
|
// we no longer need camera translation, only rotation
|
||||||
::glMultMatrixd( glm::value_ptr( glm::dmat4( glm::dmat3( worldcamera ))));
|
::glMultMatrixd( glm::value_ptr( glm::dmat4( glm::dmat3( worldcamera ))));
|
||||||
|
|
||||||
Render( &World.Environment );
|
Render( &World.Environment );
|
||||||
Render( &World.Ground );
|
Render( &World.Ground );
|
||||||
|
|
||||||
@@ -538,19 +539,26 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case GL_LINES: {
|
case GL_LINES: {
|
||||||
if( ( Node->m_geometry == NULL )
|
if( ( Node->Piece->geometry == NULL )
|
||||||
|| ( Node->fLineThickness > 0.0 ) ) {
|
|| ( Node->fLineThickness > 0.0 ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// setup
|
// setup
|
||||||
// w zaleznosci od koloru swiatla
|
auto const distance = std::sqrt( distancesquared );
|
||||||
|
auto const linealpha =
|
||||||
|
10.0 * Node->fLineThickness
|
||||||
|
/ std::max(
|
||||||
|
0.5 * Node->m_radius + 1.0,
|
||||||
|
distance - ( 0.5 * Node->m_radius ) );
|
||||||
::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(
|
1.0 ) ) ); // if the thickness is defined negative, lines are always drawn opaque
|
||||||
1.0,
|
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 );
|
||||||
1000.0 * Node->fLineThickness / ( distancesquared + 1.0 ) ) ) ) );
|
if( linewidth > 1.0 ) {
|
||||||
|
::glLineWidth( static_cast<float>( linewidth ) );
|
||||||
|
}
|
||||||
|
|
||||||
GfxRenderer.Bind( 0 );
|
GfxRenderer.Bind( 0 );
|
||||||
|
|
||||||
@@ -559,16 +567,18 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
|||||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
|
||||||
// render
|
// render
|
||||||
m_geometry.draw( Node->m_geometry );
|
m_geometry.draw( Node->Piece->geometry );
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
|
|
||||||
|
if( linewidth > 1.0 ) { ::glLineWidth( 1.0f ); }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GL_TRIANGLES: {
|
case GL_TRIANGLES: {
|
||||||
if( ( Node->m_geometry == NULL )
|
if( ( Node->Piece->geometry == NULL )
|
||||||
|| ( ( Node->iFlags & 0x10 ) == 0 ) ) {
|
|| ( ( Node->iFlags & 0x10 ) == 0 ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -582,7 +592,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
|||||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
|
||||||
// render
|
// render
|
||||||
m_geometry.draw( Node->m_geometry );
|
m_geometry.draw( Node->Piece->geometry );
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
@@ -750,7 +760,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
|||||||
// ...luminance
|
// ...luminance
|
||||||
if( Global::fLuminance < Submodel->fLight ) {
|
if( Global::fLuminance < Submodel->fLight ) {
|
||||||
// zeby swiecilo na kolorowo
|
// zeby swiecilo na kolorowo
|
||||||
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr(Submodel->f4Diffuse) );
|
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( Submodel->f4Diffuse * Submodel->f4Emision.a ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// main draw call
|
// main draw call
|
||||||
@@ -772,7 +782,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
|||||||
|
|
||||||
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) // kąt większy niż maksymalny stożek swiatła
|
if( Submodel->fCosViewAngle > Submodel->fCosFalloffAngle ) // kąt większy niż maksymalny stożek swiatła
|
||||||
{
|
{
|
||||||
float lightlevel = 1.0f;
|
float lightlevel = 1.0f; // TODO, TBD: parameter to control light strength
|
||||||
// view angle attenuation
|
// view angle attenuation
|
||||||
float const anglefactor = ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
|
float const anglefactor = ( Submodel->fCosViewAngle - Submodel->fCosFalloffAngle ) / ( 1.0f - Submodel->fCosFalloffAngle );
|
||||||
// distance attenuation. NOTE: since it's fixed pipeline with built-in gamma correction we're using linear attenuation
|
// distance attenuation. NOTE: since it's fixed pipeline with built-in gamma correction we're using linear attenuation
|
||||||
@@ -946,7 +956,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
|||||||
}
|
}
|
||||||
float const linealpha = static_cast<float>(
|
float const linealpha = static_cast<float>(
|
||||||
std::min(
|
std::min(
|
||||||
1.2,
|
1.25,
|
||||||
5000 * Node->hvTraction->WireThickness / ( distancesquared + 1.0 ) ) ); // zbyt grube nie są dobre
|
5000 * Node->hvTraction->WireThickness / ( distancesquared + 1.0 ) ) ); // zbyt grube nie są dobre
|
||||||
::glLineWidth( linealpha );
|
::glLineWidth( linealpha );
|
||||||
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
// McZapkie-261102: kolor zalezy od materialu i zasniedzenia
|
||||||
@@ -982,17 +992,23 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case GL_LINES: {
|
case GL_LINES: {
|
||||||
if( ( Node->m_geometry == NULL )
|
if( ( Node->Piece->geometry == NULL )
|
||||||
|| ( Node->fLineThickness < 0.0 ) ) {
|
|| ( Node->fLineThickness < 0.0 ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// setup
|
// setup
|
||||||
auto const linewidth = clamp( 100.0 * Node->fLineThickness / ( distancesquared + 1.0 ), 1.0, 10.0 );
|
auto const distance = std::sqrt( distancesquared );
|
||||||
|
auto const linealpha =
|
||||||
|
10.0 * Node->fLineThickness
|
||||||
|
/ std::max(
|
||||||
|
0.5 * Node->m_radius + 1.0,
|
||||||
|
distance - ( 0.5 * Node->m_radius ) );
|
||||||
::glColor4fv(
|
::glColor4fv(
|
||||||
glm::value_ptr(
|
glm::value_ptr(
|
||||||
glm::vec4(
|
glm::vec4(
|
||||||
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
|
Node->Diffuse * glm::make_vec3( Global::DayLight.ambient ), // w zaleznosci od koloru swiatla
|
||||||
std::min( 1.0, linewidth ) ) ) );
|
std::min( 1.0, linealpha ) ) ) );
|
||||||
|
auto const linewidth = clamp( 0.5 * linealpha + Node->fLineThickness * Node->m_radius / 1000.0, 1.0, 32.0 );
|
||||||
if( linewidth > 1.0 ) {
|
if( linewidth > 1.0 ) {
|
||||||
::glLineWidth( static_cast<float>(linewidth) );
|
::glLineWidth( static_cast<float>(linewidth) );
|
||||||
}
|
}
|
||||||
@@ -1004,20 +1020,18 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
|||||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
|
||||||
// render
|
// render
|
||||||
m_geometry.draw( Node->m_geometry );
|
m_geometry.draw( Node->Piece->geometry );
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
if( linewidth > 1.0 ) {
|
|
||||||
::glLineWidth( 1.0f );
|
|
||||||
}
|
|
||||||
|
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
|
|
||||||
|
if( linewidth > 1.0 ) { ::glLineWidth( 1.0f ); }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GL_TRIANGLES: {
|
case GL_TRIANGLES: {
|
||||||
if( ( Node->m_geometry == NULL )
|
if( ( Node->Piece->geometry == NULL )
|
||||||
|| ( ( Node->iFlags & 0x20 ) == 0 ) ) {
|
|| ( ( Node->iFlags & 0x20 ) == 0 ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1031,7 +1045,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
|||||||
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
|
||||||
|
|
||||||
// render
|
// render
|
||||||
m_geometry.draw( Node->m_geometry );
|
m_geometry.draw( Node->Piece->geometry );
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
@@ -1188,7 +1202,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
|||||||
// ...luminance
|
// ...luminance
|
||||||
if( Global::fLuminance < Submodel->fLight ) {
|
if( Global::fLuminance < Submodel->fLight ) {
|
||||||
// zeby swiecilo na kolorowo
|
// zeby swiecilo na kolorowo
|
||||||
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr(Submodel->f4Diffuse) );
|
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( Submodel->f4Diffuse * Submodel->f4Emision.a ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// main draw call
|
// main draw call
|
||||||
@@ -1311,7 +1325,7 @@ opengl_renderer::Update ( double const Deltatime ) {
|
|||||||
else if( framerate > 60.0 ) { targetsegments = 225; targetfactor = 1.5f; }
|
else if( framerate > 60.0 ) { targetsegments = 225; targetfactor = 1.5f; }
|
||||||
else if( framerate > 30.0 ) { targetsegments = 90; targetfactor = Global::ScreenHeight / 768.0f; }
|
else if( framerate > 30.0 ) { targetsegments = 90; targetfactor = Global::ScreenHeight / 768.0f; }
|
||||||
else { targetsegments = 9; targetfactor = Global::ScreenHeight / 768.0f * 0.75f; }
|
else { targetsegments = 9; targetfactor = Global::ScreenHeight / 768.0f * 0.75f; }
|
||||||
|
/*
|
||||||
if( targetsegments > Global::iSegmentsRendered ) {
|
if( targetsegments > Global::iSegmentsRendered ) {
|
||||||
|
|
||||||
Global::iSegmentsRendered = std::min( targetsegments, Global::iSegmentsRendered + 5 );
|
Global::iSegmentsRendered = std::min( targetsegments, Global::iSegmentsRendered + 5 );
|
||||||
@@ -1320,6 +1334,7 @@ opengl_renderer::Update ( double const Deltatime ) {
|
|||||||
|
|
||||||
Global::iSegmentsRendered = std::max( targetsegments, Global::iSegmentsRendered - 5 );
|
Global::iSegmentsRendered = std::max( targetsegments, Global::iSegmentsRendered - 5 );
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if( targetfactor > Global::fDistanceFactor ) {
|
if( targetfactor > Global::fDistanceFactor ) {
|
||||||
|
|
||||||
Global::fDistanceFactor = std::min( targetfactor, Global::fDistanceFactor + 0.05f );
|
Global::fDistanceFactor = std::min( targetfactor, Global::fDistanceFactor + 0.05f );
|
||||||
@@ -1343,6 +1358,8 @@ opengl_renderer::Update ( double const Deltatime ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add garbage collection and other less frequent works here
|
// TODO: add garbage collection and other less frequent works here
|
||||||
|
m_geometry.update();
|
||||||
|
|
||||||
if( true == DebugModeFlag ) {
|
if( true == DebugModeFlag ) {
|
||||||
m_debuginfo = m_textures.info();
|
m_debuginfo = m_textures.info();
|
||||||
}
|
}
|
||||||
|
|||||||
22
uilayer.cpp
22
uilayer.cpp
@@ -164,12 +164,22 @@ void
|
|||||||
ui_layer::render_background() {
|
ui_layer::render_background() {
|
||||||
|
|
||||||
if( m_background == 0 ) return;
|
if( m_background == 0 ) return;
|
||||||
|
|
||||||
// NOTE: we limit/expect the background to come with 4:3 ratio.
|
// NOTE: we limit/expect the background to come with 4:3 ratio.
|
||||||
// TODO, TBD: if we expose texture width or ratio from texture object, this limitation could be lifted
|
// TODO, TBD: if we expose texture width or ratio from texture object, this limitation could be lifted
|
||||||
|
|
||||||
GfxRenderer.Bind( m_background );
|
GfxRenderer.Bind( m_background );
|
||||||
quad( float4( 0.0f, 0.0f, 1024.0f, 768.0f ), float4( 1.0f, 1.0f, 1.0f, 1.0f ) );
|
auto const height { 768.0f };
|
||||||
|
auto const &texture = GfxRenderer.Texture( m_background );
|
||||||
|
float const width = (
|
||||||
|
texture.width() == texture.height() ?
|
||||||
|
1024.0f : // legacy mode, square texture displayed as 4:3 image
|
||||||
|
texture.width() / ( texture.height() / 768.0f ) );
|
||||||
|
quad(
|
||||||
|
float4(
|
||||||
|
( 1024.0f * 0.5f ) - ( width * 0.5f ),
|
||||||
|
( 768.0f * 0.5f ) - ( height * 0.5f ),
|
||||||
|
( 1024.0f * 0.5f ) - ( width * 0.5f ) + width,
|
||||||
|
( 768.0f * 0.5f ) - ( height * 0.5f ) + height ),
|
||||||
|
float4( 1.0f, 1.0f, 1.0f, 1.0f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -200,7 +210,11 @@ ui_layer::quad( float4 const &Coordinates, float4 const &Color ) {
|
|||||||
Global::iWindowHeight / 768.0 :
|
Global::iWindowHeight / 768.0 :
|
||||||
Global::iWindowHeight / 768.0 * screenratio / ( 4.0f / 3.0f ) );
|
Global::iWindowHeight / 768.0 * screenratio / ( 4.0f / 3.0f ) );
|
||||||
float const height = 768.0f * heightratio;
|
float const height = 768.0f * heightratio;
|
||||||
|
/*
|
||||||
|
float const heightratio = Global::iWindowHeight / 768.0f;
|
||||||
|
float const height = 768.0f * heightratio;
|
||||||
|
float const width = Global::iWindowWidth * heightratio;
|
||||||
|
*/
|
||||||
glColor4fv(&Color.x);
|
glColor4fv(&Color.x);
|
||||||
|
|
||||||
glBegin( GL_TRIANGLE_STRIP );
|
glBegin( GL_TRIANGLE_STRIP );
|
||||||
|
|||||||
Reference in New Issue
Block a user