mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 16:59:17 +02:00
merge, with tmj renderer
This commit is contained in:
222
Model3d.cpp
222
Model3d.cpp
@@ -66,16 +66,16 @@ TSubModel::~TSubModel()
|
||||
// wyświetlania
|
||||
};
|
||||
|
||||
void TSubModel::TextureNameSet(std::string const &Name)
|
||||
void TSubModel::Name_Material(std::string const &Name)
|
||||
{ // ustawienie nazwy submodelu, o
|
||||
// ile nie jest wczytany z E3D
|
||||
if (iFlags & 0x0200)
|
||||
{ // tylko jeżeli submodel zosta utworzony przez new
|
||||
pTexture = Name;
|
||||
m_materialname = Name;
|
||||
}
|
||||
};
|
||||
|
||||
void TSubModel::NameSet(std::string const &Name)
|
||||
void TSubModel::Name(std::string const &Name)
|
||||
{ // ustawienie nazwy submodelu, o ile
|
||||
// nie jest wczytany z E3D
|
||||
if (iFlags & 0x0200)
|
||||
@@ -180,7 +180,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
std::string token;
|
||||
parser.getTokens(1, false); // nazwa submodelu bez zmieny na małe
|
||||
parser >> token;
|
||||
NameSet(token);
|
||||
Name(token);
|
||||
if (dynamic) {
|
||||
// dla pojazdu, blokujemy załączone submodele, które mogą być nieobsługiwane
|
||||
if( ( token.size() >= 3 )
|
||||
@@ -308,50 +308,51 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
*/
|
||||
if (!parser.expectToken("map:"))
|
||||
Error("Model map parse failure!");
|
||||
std::string texture = parser.getToken<std::string>();
|
||||
if (texture == "none")
|
||||
std::string material = parser.getToken<std::string>();
|
||||
if (material == "none")
|
||||
{ // rysowanie podanym kolorem
|
||||
TextureID = 0;
|
||||
m_material = null_handle;
|
||||
iFlags |= 0x10; // rysowane w cyklu nieprzezroczystych
|
||||
}
|
||||
else if (texture.find("replacableskin") != texture.npos)
|
||||
else if (material.find("replacableskin") != material.npos)
|
||||
{ // McZapkie-060702: zmienialne skory modelu
|
||||
TextureID = -1;
|
||||
m_material = -1;
|
||||
iFlags |= (Opacity < 1.0) ? 1 : 0x10; // zmienna tekstura 1
|
||||
}
|
||||
else if (texture == "-1")
|
||||
else if (material == "-1")
|
||||
{
|
||||
TextureID = -1;
|
||||
m_material = -1;
|
||||
iFlags |= (Opacity < 1.0) ? 1 : 0x10; // zmienna tekstura 1
|
||||
}
|
||||
else if (texture == "-2")
|
||||
else if (material == "-2")
|
||||
{
|
||||
TextureID = -2;
|
||||
m_material = -2;
|
||||
iFlags |= (Opacity < 1.0) ? 2 : 0x10; // zmienna tekstura 2
|
||||
}
|
||||
else if (texture == "-3")
|
||||
else if (material == "-3")
|
||||
{
|
||||
TextureID = -3;
|
||||
m_material = -3;
|
||||
iFlags |= (Opacity < 1.0) ? 4 : 0x10; // zmienna tekstura 3
|
||||
}
|
||||
else if (texture == "-4")
|
||||
else if (material == "-4")
|
||||
{
|
||||
TextureID = -4;
|
||||
m_material = -4;
|
||||
iFlags |= (Opacity < 1.0) ? 8 : 0x10; // zmienna tekstura 4
|
||||
}
|
||||
else
|
||||
{ // jeśli tylko nazwa pliku, to dawać bieżącą ścieżkę do tekstur
|
||||
TextureNameSet(texture);
|
||||
if( texture.find_first_of( "/\\" ) == texture.npos ) {
|
||||
texture.insert( 0, Global::asCurrentTexturePath );
|
||||
Name_Material(material);
|
||||
if( material.find_first_of( "/\\" ) == material.npos ) {
|
||||
material.insert( 0, Global::asCurrentTexturePath );
|
||||
}
|
||||
TextureID = GfxRenderer.GetTextureId( texture, szTexturePath );
|
||||
m_material = GfxRenderer.Fetch_Material( material );
|
||||
// renderowanie w cyklu przezroczystych tylko jeśli:
|
||||
// 1. Opacity=0 (przejściowo <1, czy tam <100) oraz
|
||||
// 2. tekstura ma przezroczystość
|
||||
iFlags |=
|
||||
( ( ( Opacity < 1.0 )
|
||||
&& ( GfxRenderer.Texture(TextureID).has_alpha ) ) ?
|
||||
&& ( ( m_material != null_handle )
|
||||
&& ( GfxRenderer.Material( m_material ).has_alpha ) ) ) ?
|
||||
0x20 :
|
||||
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
|
||||
};
|
||||
@@ -423,7 +424,9 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
std::vector<unsigned int> sg; sg.resize( facecount ); // maski przynależności trójkątów do powierzchni
|
||||
std::vector<int> wsp; wsp.resize( iNumVerts );// z którego wierzchołka kopiować wektor normalny
|
||||
int maska = 0;
|
||||
int rawvertexcount = 0; // used to keep track of vertex indices in source file
|
||||
for (int i = 0; i < iNumVerts; ++i) {
|
||||
++rawvertexcount;
|
||||
// Ra: z konwersją na układ scenerii - będzie wydajniejsze wyświetlanie
|
||||
wsp[i] = -1; // wektory normalne nie są policzone dla tego wierzchołka
|
||||
if ((i % 3) == 0) {
|
||||
@@ -455,14 +458,12 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
>> Vertices[i].texture.t;
|
||||
if (i % 3 == 2) {
|
||||
// jeżeli wczytano 3 punkty
|
||||
if (Vertices[i ].position == Vertices[i - 1].position
|
||||
|| Vertices[i - 1].position == Vertices[i - 2].position
|
||||
|| Vertices[i - 2].position == Vertices[i ].position)
|
||||
{ // jeżeli punkty się nakładają na siebie
|
||||
if( true == degenerate( Vertices[ i ].position, Vertices[ i - 1 ].position, Vertices[ i - 2 ].position ) ) {
|
||||
// jeżeli punkty się nakładają na siebie
|
||||
--facecount; // o jeden trójkąt mniej
|
||||
iNumVerts -= 3; // czyli o 3 wierzchołki
|
||||
i -= 3; // wczytanie kolejnego w to miejsce
|
||||
WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(i) + "-" + std::to_string(i+2));
|
||||
WriteLog("Bad model: degenerated triangle ignored in: \"" + pName + "\", vertices " + std::to_string(rawvertexcount-2) + "-" + std::to_string(rawvertexcount));
|
||||
}
|
||||
if (i > 0) {
|
||||
// jeśli pierwszy trójkąt będzie zdegenerowany, to zostanie usunięty i nie ma co sprawdzać
|
||||
@@ -585,10 +586,10 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
return iNumVerts; // do określenia wielkości VBO
|
||||
};
|
||||
|
||||
int TSubModel::TriangleAdd(TModel3d *m, texture_handle tex, int tri)
|
||||
int TSubModel::TriangleAdd(TModel3d *m, material_handle tex, int tri)
|
||||
{ // dodanie trójkątów do submodelu, używane przy tworzeniu E3D terenu
|
||||
TSubModel *s = this;
|
||||
while (s ? (s->TextureID != tex) : false)
|
||||
while (s ? (s->m_material != tex) : false)
|
||||
{ // szukanie submodelu o danej teksturze
|
||||
if (s == this)
|
||||
s = Child;
|
||||
@@ -597,15 +598,15 @@ int TSubModel::TriangleAdd(TModel3d *m, texture_handle tex, int tri)
|
||||
}
|
||||
if (!s)
|
||||
{
|
||||
if (TextureID <= 0)
|
||||
if (m_material <= 0)
|
||||
s = this; // użycie głównego
|
||||
else
|
||||
{ // dodanie nowego submodelu do listy potomnych
|
||||
s = new TSubModel();
|
||||
m->AddTo(this, s);
|
||||
}
|
||||
s->TextureNameSet(GfxRenderer.Texture(tex).name);
|
||||
s->TextureID = tex;
|
||||
s->Name_Material(GfxRenderer.Material(tex).name);
|
||||
s->m_material = tex;
|
||||
s->eType = GL_TRIANGLES;
|
||||
}
|
||||
if (s->iNumVerts < 0)
|
||||
@@ -664,7 +665,7 @@ void TSubModel::DisplayLists()
|
||||
glVertex3dv(&Vertices[i].Point.x);
|
||||
*/
|
||||
glNormal3fv(glm::value_ptr(Vertices[i].normal));
|
||||
glTexCoord2fv(glm::value_ptr(Vertices[i].texture));
|
||||
glTexCoord2fv(glm::value_ptr(Vertices[i].material));
|
||||
glVertex3fv(glm::value_ptr(Vertices[i].position));
|
||||
};
|
||||
glEnd();
|
||||
@@ -798,8 +799,8 @@ int TSubModel::FlagsCheck()
|
||||
int i = 0;
|
||||
if (Child)
|
||||
{ // Child jest renderowany po danym submodelu
|
||||
if (Child->TextureID) // o ile ma teksturę
|
||||
if (Child->TextureID != TextureID) // i jest ona inna niż rodzica
|
||||
if (Child->m_material) // o ile ma teksturę
|
||||
if (Child->m_material != m_material) // i jest ona inna niż rodzica
|
||||
Child->iFlags |= 0x80; // to trzeba sprawdzać, jak z teksturami jest
|
||||
i = Child->FlagsCheck();
|
||||
iFlags |= 0x00FF0000 & ((i << 16) | (i) | (i >> 8)); // potomny, rodzeństwo i dzieci
|
||||
@@ -817,8 +818,8 @@ int TSubModel::FlagsCheck()
|
||||
if (Next)
|
||||
{ // Next jest renderowany po danym submodelu (kolejność odwrócona
|
||||
// po wczytaniu T3D)
|
||||
if (TextureID) // o ile dany ma teksturę
|
||||
if ((TextureID != Next->TextureID) ||
|
||||
if (m_material) // o ile dany ma teksturę
|
||||
if ((m_material != Next->m_material) ||
|
||||
(i & 0x00800000)) // a ma inną albo dzieci zmieniają
|
||||
iFlags |= 0x80; // to dany submodel musi sobie ją ustawiać
|
||||
i = Next->FlagsCheck();
|
||||
@@ -935,6 +936,13 @@ TSubModel *TSubModel::GetFromName(char const *search, bool i)
|
||||
|
||||
// WORD hbIndices[18]={3,0,1,5,4,2,1,0,4,1,5,3,2,3,5,2,4,0};
|
||||
|
||||
void TSubModel::RaAnimation(TAnimType a)
|
||||
{
|
||||
glm::mat4 m = OpenGLMatrices.data(GL_MODELVIEW);
|
||||
RaAnimation(m, a);
|
||||
glLoadMatrixf(glm::value_ptr(m));
|
||||
}
|
||||
|
||||
void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
{ // wykonanie animacji niezależnie od renderowania
|
||||
switch (a)
|
||||
@@ -1029,12 +1037,12 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void TSubModel::serialize_geometry( std::ostream &Output ) {
|
||||
void TSubModel::serialize_geometry( std::ostream &Output ) const {
|
||||
|
||||
if( Child ) {
|
||||
Child->serialize_geometry( Output );
|
||||
}
|
||||
if( m_geometry != 0 ) {
|
||||
if( m_geometry != null_handle ) {
|
||||
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
|
||||
vertex.serialize( Output );
|
||||
}
|
||||
@@ -1068,6 +1076,65 @@ TSubModel::create_geometry( std::size_t &Dataoffset, geometrybank_handle const &
|
||||
Next->create_geometry( Dataoffset, Bank );
|
||||
}
|
||||
|
||||
// places contained geometry in provided ground node
|
||||
void
|
||||
TSubModel::convert( TGroundNode &Groundnode ) const {
|
||||
|
||||
Groundnode.asName = pName;
|
||||
Groundnode.Ambient = f4Ambient;
|
||||
Groundnode.Diffuse = f4Diffuse;
|
||||
Groundnode.Specular = f4Specular;
|
||||
Groundnode.m_material = m_material;
|
||||
Groundnode.iFlags = (
|
||||
( true == GfxRenderer.Material( m_material ).has_alpha ) ?
|
||||
0x20 :
|
||||
0x10 );
|
||||
|
||||
if( m_geometry == null_handle ) { return; }
|
||||
|
||||
std::size_t vertexcount { 0 };
|
||||
std::vector<TGroundVertex> importedvertices;
|
||||
TGroundVertex vertex, vertex1, vertex2;
|
||||
for( auto const &sourcevertex : GfxRenderer.Vertices( m_geometry ) ) {
|
||||
vertex.position = sourcevertex.position;
|
||||
vertex.normal = sourcevertex.normal;
|
||||
vertex.texture = sourcevertex.texture;
|
||||
if( vertexcount == 0 ) { vertex1 = vertex; }
|
||||
else if( vertexcount == 1 ) { vertex2 = vertex; }
|
||||
else if( vertexcount >= 2 ) {
|
||||
if( false == degenerate( vertex1.position, vertex2.position, vertex.position ) ) {
|
||||
importedvertices.emplace_back( vertex1 );
|
||||
importedvertices.emplace_back( vertex2 );
|
||||
importedvertices.emplace_back( vertex );
|
||||
}
|
||||
}
|
||||
++vertexcount;
|
||||
if( vertexcount > 2 ) { vertexcount = 0; } // start new triangle if needed
|
||||
}
|
||||
if( Groundnode.Piece == nullptr ) {
|
||||
Groundnode.Piece = new piece_node();
|
||||
}
|
||||
Groundnode.iNumVerts = importedvertices.size();
|
||||
if( Groundnode.iNumVerts > 0 ) {
|
||||
|
||||
Groundnode.Piece->vertices.swap( importedvertices );
|
||||
|
||||
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
||||
Groundnode.pCenter += vertex.position;
|
||||
}
|
||||
Groundnode.pCenter /= Groundnode.iNumVerts;
|
||||
|
||||
double r { 0.0 };
|
||||
double tf;
|
||||
for( auto const &vertex : Groundnode.Piece->vertices ) {
|
||||
tf = glm::length2( vertex.position - glm::dvec3{ Groundnode.pCenter } );
|
||||
if( tf > r )
|
||||
r = tf;
|
||||
}
|
||||
Groundnode.fSquareRadius += r;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: leftover from static distance factor adjustment.
|
||||
// TODO: get rid of it, once we have the dynamic adjustment code in place
|
||||
void TSubModel::AdjustDist()
|
||||
@@ -1129,7 +1196,7 @@ float TSubModel::MaxY( float4x4 const &m ) {
|
||||
|
||||
auto maxy { 0.0f };
|
||||
// binary and text models invoke this function at different stages, either after or before geometry data was sent to the geometry manager
|
||||
if( m_geometry != 0 ) {
|
||||
if( m_geometry != null_handle ) {
|
||||
|
||||
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
|
||||
maxy = std::max(
|
||||
@@ -1209,11 +1276,11 @@ TSubModel *TModel3d::GetFromName(const char *sName)
|
||||
if (!sName)
|
||||
return Root; // potrzebne do terenu z E3D
|
||||
if (iFlags & 0x0200) // wczytany z pliku tekstowego, wyszukiwanie rekurencyjne
|
||||
return Root ? Root->GetFromName(sName) : NULL;
|
||||
return Root ? Root->GetFromName(sName) : nullptr;
|
||||
else // wczytano z pliku binarnego, można wyszukać iteracyjnie
|
||||
{
|
||||
// for (int i=0;i<iSubModelsCount;++i)
|
||||
return Root ? Root->GetFromName(sName) : NULL;
|
||||
return Root ? Root->GetFromName(sName) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1311,10 +1378,10 @@ void TSubModel::serialize(std::ostream &s,
|
||||
sn_utils::ls_int32(s, iNumVerts);
|
||||
sn_utils::ls_int32(s, tVboPtr);
|
||||
|
||||
if (TextureID <= 0)
|
||||
sn_utils::ls_int32(s, TextureID);
|
||||
if (m_material <= 0)
|
||||
sn_utils::ls_int32(s, m_material);
|
||||
else
|
||||
sn_utils::ls_int32(s, (int32_t)get_container_pos(textures, pTexture));
|
||||
sn_utils::ls_int32(s, (int32_t)get_container_pos(textures, m_materialname));
|
||||
|
||||
sn_utils::ls_float32(s, fVisible);
|
||||
sn_utils::ls_float32(s, fLight);
|
||||
@@ -1365,16 +1432,16 @@ void TModel3d::SaveToBinFile(std::string const &FileName)
|
||||
std::ofstream s(FileName, std::ios::binary);
|
||||
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('E', '3', 'D', '0'));
|
||||
size_t e3d_spos = s.tellp();
|
||||
auto const e3d_spos = s.tellp();
|
||||
sn_utils::ls_uint32(s, 0);
|
||||
|
||||
{
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('S', 'U', 'B', '0'));
|
||||
size_t sub_spos = s.tellp();
|
||||
auto const sub_spos = s.tellp();
|
||||
sn_utils::ls_uint32(s, 0);
|
||||
for (size_t i = 0; i < models.size(); i++)
|
||||
models[i]->serialize(s, models, names, textures, transforms);
|
||||
size_t pos = s.tellp();
|
||||
auto const pos = s.tellp();
|
||||
s.seekp(sub_spos);
|
||||
sn_utils::ls_uint32(s, (uint32_t)(4 + pos - sub_spos));
|
||||
s.seekp(pos);
|
||||
@@ -1392,11 +1459,11 @@ void TModel3d::SaveToBinFile(std::string const &FileName)
|
||||
if (textures.size())
|
||||
{
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('T', 'E', 'X', '0'));
|
||||
size_t tex_spos = s.tellp();
|
||||
auto const tex_spos = s.tellp();
|
||||
sn_utils::ls_uint32(s, 0);
|
||||
for (size_t i = 0; i < textures.size(); i++)
|
||||
sn_utils::s_str(s, textures[i]);
|
||||
size_t pos = s.tellp();
|
||||
auto const pos = s.tellp();
|
||||
s.seekp(tex_spos);
|
||||
sn_utils::ls_uint32(s, (uint32_t)(4 + pos - tex_spos));
|
||||
s.seekp(pos);
|
||||
@@ -1405,17 +1472,17 @@ void TModel3d::SaveToBinFile(std::string const &FileName)
|
||||
if (names.size())
|
||||
{
|
||||
sn_utils::ls_uint32(s, MAKE_ID4('N', 'A', 'M', '0'));
|
||||
size_t nam_spos = s.tellp();
|
||||
auto const nam_spos = s.tellp();
|
||||
sn_utils::ls_uint32(s, 0);
|
||||
for (size_t i = 0; i < names.size(); i++)
|
||||
sn_utils::s_str(s, names[i]);
|
||||
size_t pos = s.tellp();
|
||||
auto const pos = s.tellp();
|
||||
s.seekp(nam_spos);
|
||||
sn_utils::ls_uint32(s, (uint32_t)(4 + pos - nam_spos));
|
||||
s.seekp(pos);
|
||||
}
|
||||
|
||||
size_t end = s.tellp();
|
||||
auto const end = s.tellp();
|
||||
s.seekp(e3d_spos);
|
||||
sn_utils::ls_uint32(s, (uint32_t)(4 + end - e3d_spos));
|
||||
s.close();
|
||||
@@ -1470,7 +1537,7 @@ void TModel3d::deserialize(std::istream &s, size_t size, bool dynamic)
|
||||
{
|
||||
Root = nullptr;
|
||||
float4x4 *tm = nullptr;
|
||||
if( m_geometrybank == 0 ) {
|
||||
if( m_geometrybank == null_handle ) {
|
||||
m_geometrybank = GfxRenderer.Create_Bank();
|
||||
}
|
||||
|
||||
@@ -1654,20 +1721,29 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
pName = "";
|
||||
if (iTexture > 0)
|
||||
{ // obsługa stałej tekstury
|
||||
pTexture = t->at(iTexture);
|
||||
if (pTexture.find_last_of("/\\") == std::string::npos)
|
||||
pTexture.insert(0, Global::asCurrentTexturePath);
|
||||
TextureID = GfxRenderer.GetTextureId(pTexture, szTexturePath);
|
||||
if( ( iFlags & 0x30 ) == 0 ) {
|
||||
// texture-alpha based fallback if for some reason we don't have opacity flag set yet
|
||||
iFlags |=
|
||||
( GfxRenderer.Texture( TextureID ).has_alpha ?
|
||||
0x20 :
|
||||
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
|
||||
auto const materialindex = static_cast<std::size_t>( iTexture );
|
||||
if( materialindex < t->size() ) {
|
||||
m_materialname = t->at( materialindex );
|
||||
if( m_materialname.find_last_of( "/\\" ) == std::string::npos ) {
|
||||
m_materialname = Global::asCurrentTexturePath + m_materialname;
|
||||
}
|
||||
m_material = GfxRenderer.Fetch_Material( m_materialname );
|
||||
if( ( iFlags & 0x30 ) == 0 ) {
|
||||
// texture-alpha based fallback if for some reason we don't have opacity flag set yet
|
||||
iFlags |= (
|
||||
( ( m_material != null_handle )
|
||||
&& ( GfxRenderer.Material( m_material ).has_alpha ) ) ?
|
||||
0x20 :
|
||||
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorLog( "Bad model: reference to non-existent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ) );
|
||||
m_material = null_handle;
|
||||
}
|
||||
}
|
||||
else
|
||||
TextureID = iTexture;
|
||||
m_material = iTexture;
|
||||
|
||||
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu
|
||||
|
||||
@@ -1788,7 +1864,7 @@ void TModel3d::Init()
|
||||
}
|
||||
iFlags |= Root->FlagsCheck() | 0x8000; // flagi całego modelu
|
||||
if (iNumVerts) {
|
||||
if( m_geometrybank == 0 ) {
|
||||
if( m_geometrybank == null_handle ) {
|
||||
m_geometrybank = GfxRenderer.Create_Bank();
|
||||
}
|
||||
std::size_t dataoffset = 0;
|
||||
@@ -1835,17 +1911,3 @@ TSubModel *TModel3d::TerrainSquare(int n)
|
||||
r->UnFlagNext(); // blokowanie wyświetlania po Next głównej listy
|
||||
return r;
|
||||
};
|
||||
#ifdef EU07_USE_OLD_RENDERCODE
|
||||
void TModel3d::TerrainRenderVBO(int n)
|
||||
{ // renderowanie terenu z VBO
|
||||
::glPushMatrix();
|
||||
::glTranslated( -Global::pCameraPosition.x, -Global::pCameraPosition.y, -Global::pCameraPosition.z );
|
||||
TSubModel *r = Root;
|
||||
while( r ) {
|
||||
if( r->iVisible == n ) // tylko jeśli ma być widoczny w danej ramce (problem dla 0==false)
|
||||
GfxRenderer.Render( r ); // sub kolejne (Next) się nie wyrenderują
|
||||
r = r->NextGet();
|
||||
}
|
||||
::glPopMatrix();
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user