Ostatnio zmodyfikowano wczoraj o godz. 16:10
tBane Temat założony przez niniejszego użytkownika |
Wczytywanie modelu *.obj » 2025-06-26 13:21:51 Witam. Próbuję wczytać model 3D w formacie *.obj. Nie potrafię załadować face'ów modelu i nie wiem jak je opakować w std::vector. Zakomentowałem kod, który na chwilę obecną jest nieistotny, ale pozostawiłem, by wiedzieć w którym kierunku kod zmierza. #include <iostream> #include <vector> #include <string> #include <fstream> #include <sstream>
std::string ConvertWideToUtf8( std::wstring wide ) { return std::string( wide.begin(), wide.end() ); }
class Model3D { public: std::vector < float > v; std::vector < float > vt; std::vector < float > vn; std::vector < std::vector < unsigned int > > meshes; unsigned int VAO; Model3D() { } ~Model3D() { v.clear(); vt.clear(); vn.clear(); meshes.clear(); } void setPosition( float x, float y, float z ) { } void setScale( float x, float y, float z ) { } void load( std::wstring path ) { std::wifstream file( path ); if( !file.is_open() ) { std::cout << "can't open file : " << ConvertWideToUtf8( path ) << "\n"; return; } std::wstring line; while( std::getline( file, line ) ) { std::cout << ConvertWideToUtf8( line ) << "\n"; if( line.empty() ) continue; std::wistringstream ss( line ); std::wstring prefix; ss >> prefix; if( prefix == L"v" ) { float x, y, z; ss >> x >> y >> z; v.push_back( x ); v.push_back( y ); v.push_back( z ); } else if( prefix == L"vt" ) { float u, v; ss >> u >> v; vt.push_back( u ); vt.push_back( v ); } else if( prefix == L"vn" ) { float nx, ny, nz; ss >> nx >> ny >> nz; vn.push_back( nx ); vn.push_back( ny ); vn.push_back( nz ); } else if( prefix == L"f" ) { } } } void draw() { } };
int main() { Model3D test_mdl; test_mdl.load( L"mdl\\fire_tree.obj" ); return 0; }
Model # Blender 4.3.0 # www.blender.org mtllib fire_tree.mtl o Cylinder v 0.000000 -0.269176 -0.600247 v 0.000000 2.328594 -0.600247 v 0.519829 -0.269176 -0.300123 v 0.519829 2.328594 -0.300123 v 0.519829 -0.269176 0.300123 v 0.519829 2.328594 0.300123 v 0.000000 -0.269176 0.600247 v 0.000000 2.328594 0.600247 v -0.519829 -0.269176 0.300123 v -0.519829 2.328594 0.300123 v -0.519829 -0.269176 -0.300123 v -0.519829 2.328594 -0.300123 v 0.000000 2.284046 -3.439241 v 0.000000 5.126442 -1.000000 v 2.978470 2.284046 -1.719620 v 0.866025 5.126442 -0.500000 v 2.978470 2.284046 1.719620 v 0.866025 5.126442 0.500000 v 0.000000 2.284046 3.439241 v 0.000000 5.126442 1.000000 v -2.978470 2.284046 1.719620 v -0.866025 5.126442 0.500000 v -2.978470 2.284046 -1.719620 v -0.866025 5.126442 -0.500000 v 0.000000 4.599266 -2.505692 v 0.000000 6.670121 -0.728560 v 2.169993 4.599266 -1.252846 v 0.630951 6.670121 -0.364280 v 2.169993 4.599266 1.252846 v 0.630951 6.670121 0.364278 v 0.000000 4.599266 2.505692 v 0.000000 6.670121 0.728559 v -2.169993 4.599266 1.252846 v -0.630951 6.670121 0.364278 v -2.169993 4.599266 -1.252846 v -0.630951 6.670121 -0.364280 v 0.000000 6.332288 -1.727796 v 0.000000 8.688528 -0.182989 v 1.496315 6.332288 -0.863898 v 0.158471 8.688528 -0.091495 v 1.496315 6.332288 0.863898 v 0.158471 8.688528 0.091491 v 0.000000 6.332288 1.727795 v 0.000000 8.688528 0.182985 v -1.496315 6.332288 0.863898 v -0.158471 8.688528 0.091491 v -1.496315 6.332288 -0.863898 v -0.158471 8.688528 -0.091495 vn 0.5000 -0.0000 -0.8660 vn -0.5000 -0.0000 -0.8660 vn 0.4013 0.5965 -0.6951 vn 0.8026 0.5965 -0.0000 vn 0.4013 0.5965 0.6951 vn -0.4013 0.5965 0.6951 vn -0.0000 1.0000 -0.0000 vn -0.8026 0.5965 -0.0000 vn -0.4013 0.5965 -0.6951 vn -0.0000 -1.0000 -0.0000 vn 0.4348 0.4937 -0.7531 vn 0.8696 0.4938 -0.0000 vn 0.4348 0.4938 0.7531 vn -0.4348 0.4938 0.7531 vn -0.8696 0.4938 -0.0000 vn -0.4348 0.4937 -0.7531 vn 1.0000 -0.0000 -0.0000 vn 0.5000 -0.0000 0.8660 vn -0.5000 -0.0000 0.8660 vn -1.0000 -0.0000 -0.0000 vt 1.000000 0.500000 vt 1.000000 1.000000 vt 0.833333 1.000000 vt 0.833333 0.500000 vt 0.166667 0.500000 vt 0.166667 1.000000 vt -0.000000 1.000000 vt -0.000000 0.500000 vt 0.666667 1.000000 vt 0.666667 0.500000 vt 0.500000 1.000000 vt 0.500000 0.500000 vt 0.333333 1.000000 vt 0.333333 0.500000 vt 0.457846 0.370000 vt 0.250000 0.490000 vt 0.042154 0.370000 vt 0.042154 0.130000 vt 0.250000 0.010000 vt 0.457846 0.130000 vt 0.750000 0.490000 vt 0.957846 0.370000 vt 0.957846 0.130000 vt 0.750000 0.010000 vt 0.542154 0.130000 vt 0.542154 0.370000 s 1 usemtl fire_tree_green f 13/1/3 14/2/3 16/3/3 15/4/3 f 15/4/4 16/3/4 18/9/4 17/10/4 f 17/10/5 18/9/5 20/11/5 19/12/5 f 19/12/6 20/11/6 22/13/6 21/14/6 f 16/15/7 14/16/7 24/17/7 22/18/7 20/19/7 18/20/7 f 21/14/8 22/13/8 24/6/8 23/5/8 f 23/5/9 24/6/9 14/7/9 13/8/9 f 13/21/10 15/22/10 17/23/10 19/24/10 21/25/10 23/26/10 f 25/1/3 26/2/3 28/3/3 27/4/3 f 27/4/4 28/3/4 30/9/4 29/10/4 f 29/10/5 30/9/5 32/11/5 31/12/5 f 31/12/6 32/11/6 34/13/6 33/14/6 f 28/15/7 26/16/7 36/17/7 34/18/7 32/19/7 30/20/7 f 33/14/8 34/13/8 36/6/8 35/5/8 f 35/5/9 36/6/9 26/7/9 25/8/9 f 25/21/10 27/22/10 29/23/10 31/24/10 33/25/10 35/26/10 f 37/1/11 38/2/11 40/3/11 39/4/11 f 39/4/12 40/3/12 42/9/12 41/10/12 f 41/10/13 42/9/13 44/11/13 43/12/13 f 43/12/14 44/11/14 46/13/14 45/14/14 f 40/15/7 38/16/7 48/17/7 46/18/7 44/19/7 42/20/7 f 45/14/15 46/13/15 48/6/15 47/5/15 f 47/5/16 48/6/16 38/7/16 37/8/16 f 37/21/10 39/22/10 41/23/10 43/24/10 45/25/10 47/26/10 usemtl fire_tree_brown f 1/1/1 2/2/1 4/3/1 3/4/1 f 11/5/2 12/6/2 2/7/2 1/8/2 f 3/4/17 4/3/17 6/9/17 5/10/17 f 5/10/18 6/9/18 8/11/18 7/12/18 f 7/12/19 8/11/19 10/13/19 9/14/19 f 9/14/20 10/13/20 12/6/20 11/5/20 f 1/21/10 3/22/10 5/23/10 7/24/10 9/25/10 11/26/10
|
|
DejaVu |
» 2025-06-26 14:05:35 Wydawało mi się, że już pokazywałeś wcześniej kod, że potrafiłeś wczytać model i go wyświetlić. Co się zmieniło? |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-06-26 14:11:41 Wcześniej operowałem tylko na tablicy wierzchołków i tablicy normalnych. Teraz chcę pracować z face'ami i nie wiem jak sie za to zabrać. wcześniejsza wersja modeluclass Model { public: unsigned int _VAO; unsigned int _vertices_buffer; unsigned int _normals_buffer; unsigned int _VAO_normals; unsigned int _normals_vertices_buffer; Transform _transform; std::vector < float > _vertices; std::vector < float > _normals; std::vector < float > _normals_vertices; void draw() { glBindVertexArray( _VAO ); glDrawArrays( GL_TRIANGLES, 0, _vertices.size() / 5 ); glBindVertexArray( 0 ); glLineWidth( 3.0f ); glBindVertexArray( _VAO_normals ); glDrawArrays( GL_LINES, 0, _normals_vertices.size() / 2 ); glBindVertexArray( 0 ); } };
|
|
DejaVu |
» 2025-06-26 14:21:18 ChatGPT 4o: ## ✅ Gotowy kod `Model3D::load` bool Model3D::load( const std::wstring & filePath ) { std::wifstream file( filePath ); if( !file.is_open() ) { std::wcerr << L"Nie udało się otworzyć pliku: " << filePath << std::endl; return false; } std::wstring line; while( std::getline( file, line ) ) { std::wstringstream ss( line ); std::wstring prefix; ss >> prefix; if( prefix == L"v" ) { float x, y, z; ss >> x >> y >> z; vertices.emplace_back( x, y, z ); } else if( prefix == L"vt" ) { float u, v; ss >> u >> v; texCoords.emplace_back( u, v ); } else if( prefix == L"vn" ) { float x, y, z; ss >> x >> y >> z; normals.emplace_back( x, y, z ); } else if( prefix == L"f" ) { std::wstring vertexStr; std::vector < UINT > faceIndices; while( ss >> vertexStr ) { std::wistringstream vs( vertexStr ); std::wstring viStr, vtiStr, vniStr; UINT vi = 0, vti = 0, vni = 0; std::getline( vs, viStr, L'/' ); if( !viStr.empty() ) vi = std::stoi( viStr ); if( vs.peek() == L'/' ) vs.get(); if( std::getline( vs, vtiStr, L'/' ) ) { if( !vtiStr.empty() ) vti = std::stoi( vtiStr ); } if( std::getline( vs, vniStr ) ) { if( !vniStr.empty() ) vni = std::stoi( vniStr ); } if( vi > 0 ) faceIndices.push_back( vi - 1 ); } if( faceIndices.size() >= 3 ) { for( size_t i = 1; i + 1 < faceIndices.size(); ++i ) { faces.push_back( faceIndices[ 0 ] ); faces.push_back( faceIndices[ i ] ); faces.push_back( faceIndices[ i + 1 ] ); } } } } return true; }
--- ## 🧾 Wymagane struktury w klasie Upewnij się, że masz wcześniej zadeklarowane: std::vector < DirectX::XMFLOAT3 > vertices; std::vector < DirectX::XMFLOAT3 > normals; std::vector < DirectX::XMFLOAT2 > texCoords; std::vector < UINT > faces;
--- ## 📌 Co ten kod robi? * Wczytuje dane z pliku `.obj` (wierzchołki, tekstury, normalne, ściany), * Parsuje różne formaty linii `f`: `f v`, `f v/vt`, `f v//vn`, `f v/vt/vn`, * Ignoruje indeksy `vt` i `vn`, ale można je łatwo dodać do osobnych tablic, jeśli chcesz je wykorzystać w przyszłości, * Trianguluje wielokąty (np. `f 1 2 3 4`) do trójkątów. --- |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-06-27 08:36:22 Ok. Zrobiłem jak doradziłeś i dalej poszedłem tym śladem z ChatemGPT i udało mi sie wyrenderować model choinki. Co prawda jeszcze nie wczytałem materiału ale zwykłe proste podstawienie tekstury zadziałało. Teraz muszę zrobić sobie przerwę, bo nie do końca rozumiem kod i jakoś chciałbym go zoptymalizować. Dzięki za pomoc DejaVu :-) psJak skończę pisać cały program to wrzucę link do repo Efekt Kod Modelu3D + OpenGL#ifndef Model3D_hpp #define Model3D_hpp
#include <iostream> #include <vector> #include <string> #include <fstream> #include <sstream>
struct vertice { float x, y, z; float u, v; float nx, ny, nz; };
struct Mesh { std::vector < vertice > vertices; Texture * texture; };
class Model3D { public: Transform transform; std::vector < float > v; std::vector < float > vt; std::vector < float > vn; std::vector < Mesh > meshes; std::vector < std::pair < int, int >> mesh_draw_ranges; unsigned int VAO = 0; unsigned int VBO = 0; void setPosition( float x, float y, float z ) { transform.setPosition( glm::vec3( x, y, z ) ); } void setScale( float x, float y, float z ) { transform.setScale( glm::vec3( x, y, z ) ); } void load( std::wstring path ) { meshes.clear(); v.clear(); vt.clear(); vn.clear(); std::wifstream file( path ); if( !file.is_open() ) { std::cout << "Can't open file: " << ConvertWideToUtf8( path ) << "\n"; return; } std::wstring line; Mesh currentMesh; currentMesh.texture = nullptr; while( std::getline( file, line ) ) { std::wistringstream ss( line ); std::wstring prefix; ss >> prefix; if( prefix == L"v" ) { float x, y, z; ss >> x >> y >> z; v.insert( v.end(), { x, y, z } ); } else if( prefix == L"vt" ) { float u, t; ss >> u >> t; vt.insert( vt.end(), { u, t } ); } else if( prefix == L"vn" ) { float nx, ny, nz; ss >> nx >> ny >> nz; vn.insert( vn.end(), { nx, ny, nz } ); } else if( prefix == L"usemtl" ) { std::wstring mtl; ss >> mtl; if( !currentMesh.vertices.empty() ) { meshes.push_back( currentMesh ); currentMesh.vertices.clear(); } currentMesh.texture =( mtl == L"fire_tree_green" ) ? textures[ 0 ] : textures[ 1 ]; } else if( prefix == L"f" ) { std::wstring vertexStr; std::vector < vertice > triangle; while( ss >> vertexStr ) { std::wistringstream vs( vertexStr ); std::wstring viStr, vtiStr, vniStr; int vi = 0, vti = 0, vni = 0; std::getline( vs, viStr, L'/' ); if( !viStr.empty() ) vi = std::stoi( viStr ); if( vs.peek() == L'/' ) vs.get(); if( std::getline( vs, vtiStr, L'/' ) && !vtiStr.empty() ) vti = std::stoi( vtiStr ); if( std::getline( vs, vniStr ) && !vniStr.empty() ) vni = std::stoi( vniStr ); vertice vert = { }; if( vi > 0 ) { vert.x = v[( vi - 1 ) * 3 + 0 ]; vert.y = v[( vi - 1 ) * 3 + 1 ]; vert.z = v[( vi - 1 ) * 3 + 2 ]; } if( vti > 0 && vt.size() >=( vti * 2 ) ) { vert.u = vt[( vti - 1 ) * 2 + 0 ]; vert.v = vt[( vti - 1 ) * 2 + 1 ]; } if( vni > 0 && vn.size() >=( vni * 3 ) ) { vert.nx = vn[( vni - 1 ) * 3 + 0 ]; vert.ny = vn[( vni - 1 ) * 3 + 1 ]; vert.nz = vn[( vni - 1 ) * 3 + 2 ]; } triangle.push_back( vert ); } if( triangle.size() >= 3 ) { for( size_t i = 1; i + 1 < triangle.size(); ++i ) { currentMesh.vertices.push_back( triangle[ 0 ] ); currentMesh.vertices.push_back( triangle[ i ] ); currentMesh.vertices.push_back( triangle[ i + 1 ] ); } } } } if( !currentMesh.vertices.empty() ) { meshes.push_back( currentMesh ); } std::vector < vertice > buffer_vertices; mesh_draw_ranges.clear(); int offset = 0; for( const auto & mesh: meshes ) { mesh_draw_ranges.emplace_back( offset, mesh.vertices.size() ); buffer_vertices.insert( buffer_vertices.end(), mesh.vertices.begin(), mesh.vertices.end() ); offset += mesh.vertices.size(); } glGenVertexArrays( 1, & VAO ); glGenBuffers( 1, & VBO ); glBindVertexArray( VAO ); glBindBuffer( GL_ARRAY_BUFFER, VBO ); glBufferData( GL_ARRAY_BUFFER, buffer_vertices.size() * sizeof( vertice ), buffer_vertices.data(), GL_STATIC_DRAW ); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( vertice ),( void * ) offsetof( vertice, x ) ); glEnableVertexAttribArray( 0 ); glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, sizeof( vertice ),( void * ) offsetof( vertice, u ) ); glEnableVertexAttribArray( 1 ); glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, sizeof( vertice ),( void * ) offsetof( vertice, nx ) ); glEnableVertexAttribArray( 2 ); glBindVertexArray( 0 ); } void draw() { Program * program = programs[ 3 ]; for( int i = 0; i < meshes.size(); ++i ) { glBindVertexArray( VAO ); glUseProgram( program->shader_program ); if( meshes[ i ].texture ) { glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, meshes[ i ].texture->id ); std::cout << "tex id: " << meshes[ i ].texture->id << "\n"; } glUniform1i( glGetUniformLocation( program->shader_program, "texture1" ), 0 ); glUniform3f( glGetUniformLocation( program->shader_program, "fogColor" ), 0.25f, 0.25f, 0.25f ); glUniform1f( glGetUniformLocation( program->shader_program, "fogStart" ), 1.0f ); glUniform1f( glGetUniformLocation( program->shader_program, "fogEnd" ), 200.0f ); glm::mat4 view = cam->GetViewMatrix(); glm::mat4 projection = glm::perspective( glm::radians( 45.0f ), 800.0f / 600.0f, 0.1f, 400.0f ); glm::mat4 model = glm::mat4( 1.0f ); model = glm::translate( model, transform.position ); model = glm::rotate( model, glm::radians( transform.rotation.x ), glm::vec3( 1.0f, 0.0f, 0.0f ) ); model = glm::rotate( model, glm::radians( transform.rotation.y ), glm::vec3( 0.0f, 1.0f, 0.0f ) ); model = glm::rotate( model, glm::radians( transform.rotation.z ), glm::vec3( 0.0f, 0.0f, 1.0f ) ); model = glm::scale( model, transform.scale ); glUniformMatrix4fv( glGetUniformLocation( program->shader_program, "projection" ), 1, GL_FALSE, & projection[ 0 ][ 0 ] ); glUniformMatrix4fv( glGetUniformLocation( program->shader_program, "view" ), 1, GL_FALSE, & view[ 0 ][ 0 ] ); glUniformMatrix4fv( glGetUniformLocation( program->shader_program, "model" ), 1, GL_FALSE, & model[ 0 ][ 0 ] ); glm::vec3 lightPos = glm::vec3( - 5, 2, 0 ); static float lightPower = 1.0f; lightPower += 0.0001f; static float lightRange = 1.0f; lightRange += 0.0001f; glUniform3f( glGetUniformLocation( program->shader_program, "LightPosition" ), lightPos.x, lightPos.y, lightPos.z ); glUniform1f( glGetUniformLocation( program->shader_program, "LightPower" ), lightPower ); glUniform1f( glGetUniformLocation( program->shader_program, "LightRange" ), lightRange ); auto[ offset, count ] = mesh_draw_ranges[ i ]; glDrawArrays( GL_TRIANGLES, offset, count ); offset += meshes[ i ].vertices.size(); } glBindVertexArray( 0 ); } };
#endif
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-06-28 12:48:29 |
|
« 1 » |