mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 21:29:18 +02:00
Merge branch 'tmj-dev'
This commit is contained in:
89
Model3d.cpp
89
Model3d.cpp
@@ -17,8 +17,7 @@ Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Logs.h"
|
||||
#include "McZapkie/mctools.h"
|
||||
#include "usefull.h"
|
||||
#include "utilities.h"
|
||||
#include "renderer.h"
|
||||
#include "Timer.h"
|
||||
#include "mtable.h"
|
||||
@@ -295,7 +294,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
if (Opacity > 1.0f)
|
||||
Opacity *= 0.01f; // w 2013 był błąd i aby go obejść, trzeba było wpisać 10000.0
|
||||
/*
|
||||
if ((Global::iConvertModels & 1) == 0) // dla zgodności wstecz
|
||||
if ((Global.iConvertModels & 1) == 0) // dla zgodności wstecz
|
||||
Opacity = 0.0; // wszystko idzie w przezroczyste albo zależnie od tekstury
|
||||
*/
|
||||
if (!parser.expectToken("map:"))
|
||||
@@ -335,7 +334,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
{ // jeśli tylko nazwa pliku, to dawać bieżącą ścieżkę do tekstur
|
||||
Name_Material(material);
|
||||
if( material.find_first_of( "/\\" ) == material.npos ) {
|
||||
material.insert( 0, Global::asCurrentTexturePath );
|
||||
material.insert( 0, Global.asCurrentTexturePath );
|
||||
}
|
||||
m_material = GfxRenderer.Fetch_Material( material );
|
||||
// renderowanie w cyklu przezroczystych tylko jeśli:
|
||||
@@ -522,7 +521,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
}
|
||||
// Ra 15-01: należało by jeszcze uwzględnić skalowanie wprowadzane przez transformy, aby normalne po przeskalowaniu były jednostkowe
|
||||
if( glm::length2( vertexnormal ) == 0.0f ) {
|
||||
WriteLog( "Bad model: zero lenght normal vector generated for sub-model \"" + pName + "\"", logtype::model );
|
||||
WriteLog( "Bad model: zero length normal vector generated for sub-model \"" + pName + "\"", logtype::model );
|
||||
}
|
||||
Vertices[ vertexidx ].normal = (
|
||||
glm::length2( vertexnormal ) > 0.0f ?
|
||||
@@ -661,7 +660,7 @@ void TSubModel::InitialRotate(bool doit)
|
||||
// potomnych nie obracamy już, tylko ewentualnie optymalizujemy
|
||||
Child->InitialRotate( false );
|
||||
}
|
||||
else if (Global::iConvertModels & 2) {
|
||||
else if (Global.iConvertModels & 2) {
|
||||
// optymalizacja jest opcjonalna
|
||||
if ((iFlags & 0xC000) == 0x8000) // o ile nie ma animacji
|
||||
{ // jak nie ma potomnych, można wymnożyć przez transform i wyjedynkować go
|
||||
@@ -792,7 +791,7 @@ void TSubModel::SetRotateXYZ(float3 vNewAngles)
|
||||
iAnimOwner = iInstance; // zapamiętanie czyja jest animacja
|
||||
}
|
||||
|
||||
void TSubModel::SetRotateXYZ(vector3 vNewAngles)
|
||||
void TSubModel::SetRotateXYZ( Math3D::vector3 vNewAngles)
|
||||
{ // obrócenie submodelu o
|
||||
// podane kąty wokół osi
|
||||
// lokalnego układu
|
||||
@@ -812,7 +811,7 @@ void TSubModel::SetTranslate(float3 vNewTransVector)
|
||||
iAnimOwner = iInstance; // zapamiętanie czyja jest animacja
|
||||
}
|
||||
|
||||
void TSubModel::SetTranslate(vector3 vNewTransVector)
|
||||
void TSubModel::SetTranslate( Math3D::vector3 vNewTransVector)
|
||||
{ // przesunięcie submodelu (np. w kabinie)
|
||||
v_TransVector.x = vNewTransVector.x;
|
||||
v_TransVector.y = vNewTransVector.y;
|
||||
@@ -919,15 +918,15 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
break;
|
||||
case at_Hours: // godziny płynnie 12h/360°
|
||||
// glRotatef(GlobalTime->hh*30.0+GlobalTime->mm*0.5+GlobalTime->mr/120.0,0.0,1.0,0.0);
|
||||
m = glm::rotate(m, glm::radians(2.0f * (float)Global::fTimeAngleDeg), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
m = glm::rotate(m, glm::radians(2.0f * (float)Global.fTimeAngleDeg), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
break;
|
||||
case at_Hours24: // godziny płynnie 24h/360°
|
||||
// glRotatef(GlobalTime->hh*15.0+GlobalTime->mm*0.25+GlobalTime->mr/240.0,0.0,1.0,0.0);
|
||||
m = glm::rotate(m, glm::radians((float)Global::fTimeAngleDeg), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
m = glm::rotate(m, glm::radians((float)Global.fTimeAngleDeg), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
break;
|
||||
case at_Billboard: // obrót w pionie do kamery
|
||||
{
|
||||
matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
|
||||
Math3D::matrix4x4 mat; mat.OpenGL_Matrix( OpenGLMatrices.data_array( GL_MODELVIEW ) );
|
||||
float3 gdzie = float3(mat[3][0], mat[3][1], mat[3][2]); // początek układu współrzędnych submodelu względem kamery
|
||||
m = glm::mat4(1.0f);
|
||||
m = glm::translate(m, glm::vec3(gdzie.x, gdzie.y, gdzie.z)); // początek układu zostaje bez zmian
|
||||
@@ -938,8 +937,8 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
m = glm::rotate(m, glm::radians(1.5f * (float)sin(M_PI * simulation::Time.second() / 6.0)), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
break;
|
||||
case at_Sky: // animacja nieba
|
||||
m = glm::rotate(m, glm::radians((float)Global::fLatitudeDeg), glm::vec3(0.0f, 1.0f, 0.0f)); // ustawienie osi OY na północ
|
||||
m = glm::rotate(m, glm::radians((float)-fmod(Global::fTimeAngleDeg, 360.0)), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
m = glm::rotate(m, glm::radians((float)Global.fLatitudeDeg), glm::vec3(0.0f, 1.0f, 0.0f)); // ustawienie osi OY na północ
|
||||
m = glm::rotate(m, glm::radians((float)-fmod(Global.fTimeAngleDeg, 360.0)), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
break;
|
||||
case at_IK11: // ostatni element animacji szkieletowej (podudzie, stopa)
|
||||
m = glm::rotate(m, glm::radians(v_Angles.z), glm::vec3(0.0f, 1.0f, 0.0f)); // obrót względem osi pionowej (azymut)
|
||||
@@ -955,7 +954,7 @@ void TSubModel::RaAnimation(glm::mat4 &m, TAnimType a)
|
||||
if ((sm->pName[0]) >= '0')
|
||||
if ((sm->pName[0]) <= '5') // zegarek ma 6 cyfr maksymalnie
|
||||
sm->SetRotate(float3(0, 1, 0),
|
||||
-Global::fClockAngleDeg[(sm->pName[0]) - '0']);
|
||||
-Global.fClockAngleDeg[(sm->pName[0]) - '0']);
|
||||
}
|
||||
sm = sm->NextGet();
|
||||
} while (sm);
|
||||
@@ -1008,13 +1007,13 @@ TSubModel::create_geometry( std::size_t &Dataoffset, gfx::geometrybank_handle co
|
||||
|
||||
if( m_geometry != 0 ) {
|
||||
// calculate bounding radius while we're at it
|
||||
// NOTE: doesn't take into account transformation hierarchy TODO: implement it
|
||||
float squaredradius { 0.f };
|
||||
float squaredradius {};
|
||||
// if this happens to be root node it may already have non-squared radius of the largest child
|
||||
// since we're comparing squared radii, we need to square it back for correct results
|
||||
m_boundingradius *= m_boundingradius;
|
||||
auto const submodeloffset { offset( std::numeric_limits<float>::max() ) };
|
||||
for( auto const &vertex : GfxRenderer.Vertices( m_geometry ) ) {
|
||||
squaredradius = static_cast<float>( glm::length2( vertex.position ) );
|
||||
squaredradius = glm::length2( submodeloffset + vertex.position );
|
||||
if( squaredradius > m_boundingradius ) {
|
||||
m_boundingradius = squaredradius;
|
||||
}
|
||||
@@ -1122,7 +1121,6 @@ TModel3d::~TModel3d() {
|
||||
if (iFlags & 0x0200) {
|
||||
// wczytany z pliku tekstowego, submodele sprzątają same
|
||||
SafeDelete( Root );
|
||||
// Root = nullptr;
|
||||
}
|
||||
else {
|
||||
// wczytano z pliku binarnego (jest właścicielem tablic)
|
||||
@@ -1132,17 +1130,19 @@ TModel3d::~TModel3d() {
|
||||
|
||||
TSubModel *TModel3d::AddToNamed(const char *Name, TSubModel *SubModel)
|
||||
{
|
||||
TSubModel *sm = Name ? GetFromName(Name) : NULL;
|
||||
TSubModel *sm = Name ? GetFromName(Name) : nullptr;
|
||||
if( ( sm == nullptr )
|
||||
&& ( Name != nullptr ) && ( std::strcmp( Name, "none" ) != 0 ) ) {
|
||||
ErrorLog( "Bad model: parent for sub-model \"" + SubModel->pName +"\" doesn't exist or is located after in the model data", logtype::model );
|
||||
}
|
||||
AddTo(sm, SubModel); // szukanie nadrzędnego
|
||||
return sm; // zwracamy wskaźnik do nadrzędnego submodelu
|
||||
};
|
||||
|
||||
void TModel3d::AddTo(TSubModel *tmp, TSubModel *SubModel)
|
||||
{ // jedyny poprawny sposób dodawania
|
||||
// submodeli, inaczej mogą zginąć
|
||||
// przy zapisie E3D
|
||||
if (tmp)
|
||||
{ // jeśli znaleziony, podłączamy mu jako potomny
|
||||
// jedyny poprawny sposób dodawania submodeli, inaczej mogą zginąć przy zapisie E3D
|
||||
void TModel3d::AddTo(TSubModel *tmp, TSubModel *SubModel) {
|
||||
if (tmp) {
|
||||
// jeśli znaleziony, podłączamy mu jako potomny
|
||||
tmp->ChildAdd(SubModel);
|
||||
}
|
||||
else
|
||||
@@ -1180,24 +1180,26 @@ TSubModel::offset( float const Geometrytestoffsetthreshold ) const {
|
||||
// offset of zero generally means the submodel has optimized identity matrix
|
||||
// for such cases we resort to an estimate from submodel geometry
|
||||
// TODO: do proper bounding area calculation for submodel when loading mesh and grab the centre point from it here
|
||||
if( m_geometry != null_handle ) {
|
||||
auto const &vertices { GfxRenderer.Vertices( m_geometry ) };
|
||||
if( false == vertices.empty() ) {
|
||||
// transformation matrix for the submodel can still contain rotation and/or scaling,
|
||||
// so we pass the vertex positions through it rather than just grab them directly
|
||||
offset = glm::vec3();
|
||||
auto const vertexfactor { 1.f / vertices.size() };
|
||||
auto const transformationmatrix { glm::make_mat4( parentmatrix.readArray() ) };
|
||||
for( auto const &vertex : vertices ) {
|
||||
offset += glm::vec3 { transformationmatrix * glm::vec4 { vertex.position, 1 } } * vertexfactor;
|
||||
}
|
||||
auto const &vertices { (
|
||||
m_geometry != null_handle ?
|
||||
GfxRenderer.Vertices( m_geometry ) :
|
||||
Vertices ) };
|
||||
if( false == vertices.empty() ) {
|
||||
// transformation matrix for the submodel can still contain rotation and/or scaling,
|
||||
// so we pass the vertex positions through it rather than just grab them directly
|
||||
offset = glm::vec3();
|
||||
auto const vertexfactor { 1.f / vertices.size() };
|
||||
auto const transformationmatrix { glm::make_mat4( parentmatrix.readArray() ) };
|
||||
for( auto const &vertex : vertices ) {
|
||||
offset += glm::vec3 { transformationmatrix * glm::vec4 { vertex.position, 1 } } * vertexfactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( true == TestFlag( iFlags, 0x0200 ) ) {
|
||||
// flip coordinates for t3d file which wasn't yet initialized
|
||||
if( std::abs( offset.y ) > offset.z ) {
|
||||
if( ( false == Global.pWorld->InitPerformed() )
|
||||
|| ( false == Vertices.empty() ) ) {
|
||||
// NOTE, HACK: results require flipping if the model wasn't yet initialized, so we're using crude method to detect possible cases
|
||||
// TODO: sort out this mess, either unify offset lookups to take place before (or after) initialization,
|
||||
// or provide way to determine on submodel level whether the initialization took place
|
||||
@@ -1212,6 +1214,7 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
|
||||
{
|
||||
// wczytanie modelu z pliku
|
||||
std::string name = ToLower(FileName);
|
||||
std::replace(name.begin(), name.end(), '\\', '/');
|
||||
// trim extension if needed
|
||||
if( name.rfind( '.' ) != std::string::npos )
|
||||
{
|
||||
@@ -1231,7 +1234,7 @@ bool TModel3d::LoadFromFile(std::string const &FileName, bool dynamic)
|
||||
{
|
||||
if (FileExists(name + ".t3d"))
|
||||
{
|
||||
LoadFromTextFile(FileName, dynamic); // wczytanie tekstowego
|
||||
LoadFromTextFile(name + ".t3d", dynamic); // wczytanie tekstowego
|
||||
if( !dynamic ) {
|
||||
// pojazdy dopiero po ustawieniu animacji
|
||||
Init(); // generowanie siatek i zapis E3D
|
||||
@@ -1643,7 +1646,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
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_materialname = Global.asCurrentTexturePath + m_materialname;
|
||||
}
|
||||
m_material = GfxRenderer.Fetch_Material( m_materialname );
|
||||
if( ( iFlags & 0x30 ) == 0 ) {
|
||||
@@ -1709,9 +1712,7 @@ void TModel3d::LoadFromBinFile(std::string const &FileName, bool dynamic)
|
||||
{ // wczytanie modelu z pliku binarnego
|
||||
WriteLog( "Loading binary format 3d model data from \"" + FileName + "\"...", logtype::model );
|
||||
|
||||
std::string fn = FileName;
|
||||
std::replace(fn.begin(), fn.end(), '\\', '/');
|
||||
std::ifstream file(fn, std::ios::binary);
|
||||
std::ifstream file(FileName, std::ios::binary);
|
||||
|
||||
uint32_t type = sn_utils::ld_uint32(file);
|
||||
uint32_t size = sn_utils::ld_uint32(file) - 8;
|
||||
@@ -1753,7 +1754,7 @@ void TModel3d::LoadFromTextFile(std::string const &FileName, bool dynamic)
|
||||
}
|
||||
// Ra: od wersji 334 przechylany jest cały model, a nie tylko pierwszy submodel
|
||||
// ale bujanie kabiny nadal używa bananów :( od 393 przywrócone, ale z dodatkowym warunkiem
|
||||
if (Global::iConvertModels & 4)
|
||||
if (Global.iConvertModels & 4)
|
||||
{ // automatyczne banany czasem psuły przechylanie kabin...
|
||||
if (dynamic && Root)
|
||||
{
|
||||
@@ -1790,7 +1791,7 @@ void TModel3d::Init()
|
||||
std::size_t dataoffset = 0;
|
||||
Root->create_geometry( dataoffset, m_geometrybank );
|
||||
}
|
||||
if( ( Global::iConvertModels > 0 )
|
||||
if( ( Global.iConvertModels > 0 )
|
||||
&& ( false == asBinary.empty() ) ) {
|
||||
SaveToBinFile( asBinary );
|
||||
asBinary = ""; // zablokowanie powtórnego zapisu
|
||||
|
||||
Reference in New Issue
Block a user