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

merge, with tmj renderer

This commit is contained in:
milek7
2017-08-18 00:56:05 +02:00
85 changed files with 6815 additions and 3770 deletions

View File

@@ -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