import msh file,
problems: it is not correctly displayed (vertice and what happend to the texture?) todo: improve the import, remove unused garbage, add move and zoom function
This commit is contained in:
		
							
								
								
									
										79
									
								
								QtMeshViewer/Header/FileInterface.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								QtMeshViewer/Header/FileInterface.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #pragma once | ||||
| #include <fstream> | ||||
| #include <QVector> | ||||
| #include <QVector2D> | ||||
| #include <QVector3D> | ||||
| #include <QMatrix4x4> | ||||
| #include <QQuaternion> | ||||
| #include <QOpenGLFunctions> | ||||
|  | ||||
|  | ||||
| struct VertexData | ||||
| { | ||||
| 	QVector3D position; | ||||
| 	QVector2D texCoord; | ||||
| }; | ||||
|  | ||||
| enum ModelTyp { | ||||
| 	null, | ||||
| 	dynamicMesh, | ||||
| 	cloth, | ||||
| 	bone, | ||||
| 	staticMesh, | ||||
| 	shadowMesh = 6 | ||||
| }; | ||||
|  | ||||
| struct BoundingBox { | ||||
| 	QQuaternion rotation; | ||||
| 	QVector3D center; | ||||
| 	QVector3D extents; | ||||
| }; | ||||
|  | ||||
| struct Segment { | ||||
| 	std::uint32_t textureIndex = 0; | ||||
| 	QVector<VertexData> vertices; | ||||
| 	QVector<GLuint> indices; | ||||
| }; | ||||
|  | ||||
| struct Model { | ||||
| 	std::string name = ""; | ||||
| 	std::string parent = ""; | ||||
| 	ModelTyp type = null;	//TODO: should be removed | ||||
| 	std::int32_t renderFlags = -1;	//TODO: should be removed | ||||
| 	QMatrix4x4 m4x4Translation; | ||||
| 	std::vector<Segment*> segmList; | ||||
| }; | ||||
|  | ||||
| class FileInterface | ||||
| { | ||||
| public: | ||||
| 	explicit FileInterface(const char* path) | ||||
| 		: m_models(new QVector<Model*>) | ||||
| 		, m_textureNames(new QVector<std::string>) | ||||
| 	{ | ||||
| 		//open file | ||||
| 		m_file.open(path, std::ios::in | std::ios::binary); | ||||
|  | ||||
| 		if (!m_file.is_open()) | ||||
| 			throw std::invalid_argument(std::string("file not found: ") += path); | ||||
| 	}; | ||||
|  | ||||
| 	virtual ~FileInterface() | ||||
| 	{ | ||||
| 		// close file | ||||
| 		m_file.close(); | ||||
| 	}; | ||||
|  | ||||
| protected: | ||||
| 	QVector<Model*>* m_models; | ||||
| 	std::fstream m_file; | ||||
| 	QVector<std::string>* m_textureNames; | ||||
| 	BoundingBox m_sceneBbox; | ||||
|  | ||||
| 	virtual void import() = 0; | ||||
|  | ||||
| public: | ||||
| 	virtual QVector<Model*>* getModels() const { return m_models; }; | ||||
| 	virtual QVector<std::string>* getTextureNames() const { return m_textureNames; }; | ||||
| 	virtual BoundingBox getBoundingBox() const { return m_sceneBbox; }; | ||||
| }; | ||||
| @@ -1,5 +1,5 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "..\Header\FileInterface.h" | ||||
| #include <QOpenGLFunctions> | ||||
| #include <QOpenGLShaderProgram> | ||||
| #include <QOpenGLBuffer> | ||||
| @@ -17,6 +17,9 @@ private: | ||||
| 	QOpenGLBuffer m_indexBuf; | ||||
| 	QVector<QOpenGLTexture*> m_textures; | ||||
|  | ||||
| 	QVector<Model*>* m_models = Q_NULLPTR; | ||||
| 	QVector<std::string>* m_textureNames = Q_NULLPTR;	//TODO: remove, use it local and only hold the textures itself | ||||
|  | ||||
| 	void initCubeGeometry(); | ||||
| 	void initTexture(); | ||||
|  | ||||
|   | ||||
							
								
								
									
										34
									
								
								QtMeshViewer/Header/MshFile.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								QtMeshViewer/Header/MshFile.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| #pragma once | ||||
| #include "..\Header\FileInterface.h" | ||||
|  | ||||
|  | ||||
| struct ChunkHeader { | ||||
| 	char name[5]; | ||||
| 	std::uint32_t size; | ||||
| 	std::streampos position; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class MshFile : public FileInterface | ||||
| { | ||||
| public: | ||||
| 	explicit MshFile(const char* path); | ||||
| 	virtual ~MshFile(); | ||||
|  | ||||
| private: | ||||
| 	virtual void import() Q_DECL_OVERRIDE Q_DECL_FINAL; | ||||
|  | ||||
| 	void loadChunks(std::list<ChunkHeader*> &destination, std::streampos start, const std::uint32_t length); | ||||
|  | ||||
| 	void analyseMsh2Chunks(std::list<ChunkHeader*> &chunkList); | ||||
|  | ||||
| 	void analyseMatdChunks(std::list<ChunkHeader*> &chunkList); | ||||
|  | ||||
| 	void analyseModlChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); | ||||
| 	void analyseGeomChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); | ||||
| 	void analyseSegmChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); | ||||
| 	void analyseClthChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); | ||||
|  | ||||
| 	void readVertex(Segment* dataDestination, std::streampos position); | ||||
| 	void readUV(Segment* dataDestination, std::streampos position); | ||||
| }; | ||||
| @@ -1,14 +1,5 @@ | ||||
| #include "..\Header\GeometryEngine.h" | ||||
|  | ||||
| #include <QVector2D> | ||||
| #include <QVector3D> | ||||
|  | ||||
|  | ||||
| struct VertexData | ||||
| { | ||||
| 	QVector3D position; | ||||
| 	QVector2D texCoord; | ||||
| }; | ||||
| #include "..\Header\MshFile.h" | ||||
|  | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////// | ||||
| @@ -45,66 +36,89 @@ GeometryEngine::~GeometryEngine() | ||||
| void GeometryEngine::initCubeGeometry() | ||||
| { | ||||
|  | ||||
| 	QVector<VertexData> vertices = { | ||||
|         // Vertex data for face 0 | ||||
|         {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(0.0f, 0.0f)},  // v0 | ||||
|         {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D(0.33f, 0.0f)}, // v1 | ||||
|         {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(0.0f, 0.5f)},  // v2 | ||||
|         {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v3 | ||||
| 	try | ||||
| 	{ | ||||
| 		MshFile file("..\\Release\\Msh\\cube.msh"); | ||||
| 		m_models = file.getModels(); | ||||
| 		//TODO use models local, apply MVP directly to the vertex, save size and tex index info | ||||
|  | ||||
|         // Vertex data for face 1 | ||||
|         {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D( 0.0f, 0.5f)}, // v4 | ||||
|         {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.5f)}, // v5 | ||||
|         {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.0f, 1.0f)},  // v6 | ||||
|         {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v7 | ||||
|  | ||||
|         // Vertex data for face 2 | ||||
|         {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v8 | ||||
|         {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(1.0f, 0.5f)},  // v9 | ||||
|         {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.66f, 1.0f)}, // v10 | ||||
|         {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(1.0f, 1.0f)},  // v11 | ||||
|  | ||||
|         // Vertex data for face 3 | ||||
|         {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v12 | ||||
|         {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(1.0f, 0.0f)},  // v13 | ||||
|         {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v14 | ||||
|         {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(1.0f, 0.5f)},  // v15 | ||||
|  | ||||
|         // Vertex data for face 4 | ||||
|         {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.0f)}, // v16 | ||||
|         {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v17 | ||||
|         {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v18 | ||||
|         {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D(0.66f, 0.5f)}, // v19 | ||||
|  | ||||
|         // Vertex data for face 5 | ||||
|         {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v20 | ||||
|         {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.66f, 0.5f)}, // v21 | ||||
|         {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v22 | ||||
|         {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.66f, 1.0f)}  // v23 | ||||
|     }; | ||||
|  | ||||
| 	QVector<GLushort> indices = { | ||||
| 		0,1,2,		//vorne (4) | ||||
| 		3,2,1, | ||||
| 		4,5,7,		//rechts (1) | ||||
| 		6,4,7, | ||||
| 		8,9,11,		//hinten (3)* | ||||
| 		8,11,10, | ||||
| 		14,12,13,	//links (6)* | ||||
| 		14,13,15, | ||||
| 		18,16,17,	//unten (5) | ||||
| 		19,18,17, | ||||
| 		23,22,20,	//oben (2)* | ||||
| 		23,20,21 | ||||
| 	}; | ||||
| 		//TODO: handle the textures | ||||
| 	} | ||||
| 	catch (std::invalid_argument e) | ||||
| 	{ | ||||
| 		//TODO: make a cool message box | ||||
| 		auto msg = e.what(); | ||||
| 	} | ||||
|  | ||||
| 	// Transfer vertex data to VBO 0 | ||||
| 	m_arrayBuf.bind(); | ||||
| 	m_arrayBuf.allocate(vertices.data(), vertices.size() * sizeof(VertexData)); | ||||
| 	m_arrayBuf.allocate(m_models->first()->segmList.front()->vertices.data(), m_models->first()->segmList.front()->vertices.size() * sizeof(VertexData)); | ||||
|  | ||||
| 	// Transfer index data to VBO 1 | ||||
| 	m_indexBuf.bind(); | ||||
| 	m_indexBuf.allocate(indices.data(), indices.size() * sizeof(GLushort)); | ||||
| 	m_indexBuf.allocate(m_models->first()->segmList.front()->indices.data(), m_models->first()->segmList.front()->indices.size() * sizeof(GLushort)); | ||||
|  | ||||
|  | ||||
| 	//QVector<VertexData> vertices = { | ||||
|  //       // Vertex data for face 0 | ||||
|  //       {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(0.0f, 0.0f)},  // v0 | ||||
|  //       {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D(0.33f, 0.0f)}, // v1 | ||||
|  //       {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(0.0f, 0.5f)},  // v2 | ||||
|  //       {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v3 | ||||
|  | ||||
|  //       // Vertex data for face 1 | ||||
|  //       {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D( 0.0f, 0.5f)}, // v4 | ||||
|  //       {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.5f)}, // v5 | ||||
|  //       {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.0f, 1.0f)},  // v6 | ||||
|  //       {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v7 | ||||
|  | ||||
|  //       // Vertex data for face 2 | ||||
|  //       {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v8 | ||||
|  //       {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(1.0f, 0.5f)},  // v9 | ||||
|  //       {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.66f, 1.0f)}, // v10 | ||||
|  //       {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(1.0f, 1.0f)},  // v11 | ||||
|  | ||||
|  //       // Vertex data for face 3 | ||||
|  //       {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v12 | ||||
|  //       {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(1.0f, 0.0f)},  // v13 | ||||
|  //       {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v14 | ||||
|  //       {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(1.0f, 0.5f)},  // v15 | ||||
|  | ||||
|  //       // Vertex data for face 4 | ||||
|  //       {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.0f)}, // v16 | ||||
|  //       {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v17 | ||||
|  //       {QVector3D(-1.0f, -1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v18 | ||||
|  //       {QVector3D( 1.0f, -1.0f,  1.0f), QVector2D(0.66f, 0.5f)}, // v19 | ||||
|  | ||||
|  //       // Vertex data for face 5 | ||||
|  //       {QVector3D(-1.0f,  1.0f,  1.0f), QVector2D(0.33f, 0.5f)}, // v20 | ||||
|  //       {QVector3D( 1.0f,  1.0f,  1.0f), QVector2D(0.66f, 0.5f)}, // v21 | ||||
|  //       {QVector3D(-1.0f,  1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v22 | ||||
|  //       {QVector3D( 1.0f,  1.0f, -1.0f), QVector2D(0.66f, 1.0f)}  // v23 | ||||
|  //   }; | ||||
|  | ||||
| 	//QVector<GLushort> indices = { | ||||
| 	//	0,1,2,		//vorne (4) | ||||
| 	//	3,2,1, | ||||
| 	//	4,5,7,		//rechts (1) | ||||
| 	//	6,4,7, | ||||
| 	//	8,9,11,		//hinten (3)* | ||||
| 	//	8,11,10, | ||||
| 	//	14,12,13,	//links (6)* | ||||
| 	//	14,13,15, | ||||
| 	//	18,16,17,	//unten (5) | ||||
| 	//	19,18,17, | ||||
| 	//	23,22,20,	//oben (2)* | ||||
| 	//	23,20,21 | ||||
| 	//}; | ||||
|  | ||||
| 	//// Transfer vertex data to VBO 0 | ||||
| 	//m_arrayBuf.bind(); | ||||
| 	//m_arrayBuf.allocate(vertices.data(), vertices.size() * sizeof(VertexData)); | ||||
|  | ||||
| 	//// Transfer index data to VBO 1 | ||||
| 	//m_indexBuf.bind(); | ||||
| 	//m_indexBuf.allocate(indices.data(), indices.size() * sizeof(GLushort)); | ||||
|  | ||||
| 	// load the texture | ||||
| 	initTexture(); | ||||
|   | ||||
							
								
								
									
										607
									
								
								QtMeshViewer/Source/MshFile.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										607
									
								
								QtMeshViewer/Source/MshFile.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,607 @@ | ||||
| #include "..\Header\MshFile.h" | ||||
| #include <iostream> | ||||
|  | ||||
|  | ||||
| // helper function to save data from file to any variable type | ||||
| #define F2V(variableName) reinterpret_cast<char*>(&variableName) | ||||
|  | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////// | ||||
| // public constructor/destructor | ||||
|  | ||||
| MshFile::MshFile(const char * path) | ||||
| 	: FileInterface(path) | ||||
| { | ||||
| 	import(); | ||||
| } | ||||
|  | ||||
| MshFile::~MshFile() | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////// | ||||
| // private functions | ||||
|  | ||||
| void MshFile::import() | ||||
| { | ||||
| 	// go to file size information | ||||
| 	m_file.seekg(4); | ||||
|  | ||||
| 	std::uint32_t tmp_fileSize; | ||||
| 	std::list<ChunkHeader*> tmp_mainChunks; | ||||
|  | ||||
| 	// get all chunks under HEDR | ||||
| 	m_file.read(F2V(tmp_fileSize), sizeof(tmp_fileSize)); | ||||
| 	loadChunks(tmp_mainChunks, m_file.tellg(), tmp_fileSize); | ||||
|  | ||||
| 	// evaulate HEDR subchunks (= find MSH2) | ||||
| 	for (ChunkHeader* it : tmp_mainChunks) | ||||
| 	{ | ||||
| 		if (!strcmp("MSH2", it->name)) | ||||
| 		{ | ||||
| 			// get all subchunks | ||||
| 			std::list<ChunkHeader*> tmp_msh2Chunks; | ||||
| 			loadChunks(tmp_msh2Chunks, it->position, it->size); | ||||
|  | ||||
| 			// evaluate MSH2 subchunks | ||||
| 			analyseMsh2Chunks(tmp_msh2Chunks); | ||||
|  | ||||
| 			// clean up | ||||
| 			while (!tmp_msh2Chunks.empty()) | ||||
| 			{ | ||||
| 				ChunkHeader* curs = tmp_msh2Chunks.front(); | ||||
| 				tmp_msh2Chunks.pop_front(); | ||||
| 				delete curs; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// clean up | ||||
| 	while (!tmp_mainChunks.empty()) | ||||
| 	{ | ||||
| 		ChunkHeader* cur = tmp_mainChunks.front(); | ||||
| 		tmp_mainChunks.pop_front(); | ||||
| 		delete cur; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MshFile::loadChunks(std::list<ChunkHeader*>& destination, std::streampos start, const std::uint32_t length) | ||||
| { | ||||
| 	// jump to first chunk | ||||
| 	m_file.seekg(start); | ||||
|  | ||||
| 	do | ||||
| 	{ | ||||
| 		ChunkHeader* tmp_header = new ChunkHeader(); | ||||
|  | ||||
| 		// get information | ||||
| 		m_file.read(F2V(tmp_header->name[0]), sizeof(tmp_header->name) - 1); | ||||
| 		m_file.read(F2V(tmp_header->size), sizeof(tmp_header->size)); | ||||
| 		tmp_header->position = m_file.tellg(); | ||||
|  | ||||
| 		// store information | ||||
| 		destination.push_back(tmp_header); | ||||
|  | ||||
| 		// jump to next header | ||||
| 		m_file.seekg(tmp_header->size, std::ios_base::cur); | ||||
|  | ||||
| 		// out of file. Maybe a size information is corrupted | ||||
| 		if (!m_file.good()) | ||||
| 		{ | ||||
| 			//TODO: different way for output | ||||
| 			std::cout << "WARNING: corrupted file. Trying to continue" << std::endl; | ||||
| 			m_file.clear(); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 	} while (m_file.tellg() - start != length); | ||||
| } | ||||
|  | ||||
| void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList) | ||||
| { | ||||
| 	for (auto& it : chunkList) | ||||
| 	{ | ||||
| 		// scene information | ||||
| 		if (!strcmp("SINF", it->name)) | ||||
| 		{ | ||||
| 			// get SINF subchunks | ||||
| 			std::list<ChunkHeader*> tmp_sinfChunks; | ||||
| 			loadChunks(tmp_sinfChunks, it->position, it->size); | ||||
|  | ||||
| 			// evaluate SINF subchunks | ||||
| 			for (auto& it : tmp_sinfChunks) | ||||
| 			{ | ||||
| 				if (!strcmp("BBOX", it->name)) | ||||
| 				{ | ||||
| 					m_file.seekg(it->position); | ||||
|  | ||||
| 					// read in the quaternion | ||||
| 					float tmp_quat[4]; | ||||
| 					for (int i = 0; i < 4; i++) | ||||
| 						m_file.read(F2V(tmp_quat[i]), sizeof(float)); | ||||
|  | ||||
| 					m_sceneBbox.rotation.setX(tmp_quat[0]); | ||||
| 					m_sceneBbox.rotation.setY(tmp_quat[1]); | ||||
| 					m_sceneBbox.rotation.setZ(tmp_quat[2]); | ||||
| 					m_sceneBbox.rotation.setScalar(tmp_quat[3]); | ||||
|  | ||||
| 					//read in the center | ||||
| 					for (int i = 0; i < 3; i++) | ||||
| 						m_file.read(F2V(m_sceneBbox.center[i]), sizeof(float)); | ||||
|  | ||||
| 					//read in the extents | ||||
| 					for (int i = 0; i < 3; i++) | ||||
| 						m_file.read(F2V(m_sceneBbox.extents[i]), sizeof(float)); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// clean up SINF subchunks | ||||
| 			for (ChunkHeader* it : tmp_sinfChunks) | ||||
| 				delete it; | ||||
| 		} | ||||
|  | ||||
| 		// material list | ||||
| 		else if (!strcmp("MATL", it->name)) | ||||
| 		{ | ||||
| 			// "useless" information how many MATD follow, jump over it | ||||
| 			m_file.seekg(it->position); | ||||
| 			m_file.seekg(sizeof(std::uint32_t), std::ios_base::cur); | ||||
|  | ||||
| 			// get all MATL subchunk | ||||
| 			std::list<ChunkHeader*> tmp_matlChunks; | ||||
| 			loadChunks(tmp_matlChunks, m_file.tellg(), it->size - 4); | ||||
|  | ||||
| 			// evaluate MATL subchunks | ||||
| 			for (auto& it : tmp_matlChunks) | ||||
| 			{ | ||||
| 				// This shouldn't be anything else than MATD | ||||
| 				if (!strcmp("MATD", it->name)) | ||||
| 				{ | ||||
| 					// get all subchunks from MATD | ||||
| 					std::list<ChunkHeader*> tmp_matdChunks; | ||||
| 					loadChunks(tmp_matdChunks, it->position, it->size); | ||||
|  | ||||
| 					m_textureNames->push_back(""); | ||||
|  | ||||
| 					// analyse MATD subchunks | ||||
| 					analyseMatdChunks(tmp_matdChunks); | ||||
|  | ||||
| 					// clean up MATD subchunks | ||||
| 					while (!tmp_matdChunks.empty()) | ||||
| 					{ | ||||
| 						ChunkHeader* cur = tmp_matdChunks.front(); | ||||
| 						tmp_matdChunks.pop_front(); | ||||
| 						delete cur; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// clean up MATL subchunks | ||||
| 			while (!tmp_matlChunks.empty()) | ||||
| 			{ | ||||
| 				ChunkHeader* cur = tmp_matlChunks.front(); | ||||
| 				tmp_matlChunks.pop_front(); | ||||
| 				delete cur; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// model | ||||
| 		else if (!strcmp("MODL", it->name)) | ||||
| 		{ | ||||
| 			Model* new_model = new Model; | ||||
|  | ||||
| 			// get all MODL subchunks | ||||
| 			std::list<ChunkHeader*> tmp_chunks; | ||||
| 			loadChunks(tmp_chunks, it->position, it->size); | ||||
|  | ||||
| 			// evaluate MODL subchunks | ||||
| 			analyseModlChunks(new_model, tmp_chunks); | ||||
|  | ||||
| 			//clean up MODL subchunks | ||||
| 			while (!tmp_chunks.empty()) | ||||
| 			{ | ||||
| 				ChunkHeader* cur = tmp_chunks.front(); | ||||
| 				tmp_chunks.pop_front(); | ||||
| 				delete cur; | ||||
| 			} | ||||
|  | ||||
| 			// save Model data | ||||
| 			m_models->push_back(new_model); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList) | ||||
| { | ||||
| 	for (auto& it : chunkList) | ||||
| 	{ | ||||
| 		if (!strcmp("TX0D", it->name)) | ||||
| 		{ | ||||
| 			m_file.seekg(it->position); | ||||
| 			char* buffer = new char[it->size + 1]; | ||||
| 			*buffer = { 0 }; | ||||
| 			m_file.read(buffer, it->size); | ||||
| 			m_textureNames->back() = buffer; | ||||
| 			delete[] buffer; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList) | ||||
| { | ||||
| 	for (auto& it : chunkList) | ||||
| 	{ | ||||
| 		// model type | ||||
| 		if (!strcmp("MTYP", it->name)) | ||||
| 		{ | ||||
| 			m_file.seekg(it->position); | ||||
| 			std::uint32_t tmp_type; | ||||
| 			m_file.read(F2V(tmp_type), sizeof(tmp_type)); | ||||
| 			dataDestination->type = (ModelTyp)tmp_type; | ||||
| 		} | ||||
|  | ||||
| 		// parent name | ||||
| 		else if (!strcmp("PRNT", it->name)) | ||||
| 		{ | ||||
| 			m_file.seekg(it->position); | ||||
| 			char* buffer = new char[it->size + 1]; | ||||
| 			*buffer = { 0 }; | ||||
| 			m_file.read(buffer, it->size); | ||||
| 			dataDestination->parent = buffer; | ||||
| 			delete[] buffer; | ||||
| 		} | ||||
|  | ||||
| 		// model name | ||||
| 		else if (!strcmp("NAME", it->name)) | ||||
| 		{ | ||||
| 			m_file.seekg(it->position); | ||||
| 			char* buffer = new char[it->size + 1]; | ||||
| 			*buffer = { 0 }; | ||||
| 			m_file.read(buffer, it->size); | ||||
| 			dataDestination->name = buffer; | ||||
| 			delete[] buffer; | ||||
| 		} | ||||
|  | ||||
| 		// render flags | ||||
| 		else if (!strcmp("FLGS", it->name)) | ||||
| 		{ | ||||
| 			m_file.seekg(it->position); | ||||
| 			m_file.read(F2V(dataDestination->renderFlags), sizeof(dataDestination->renderFlags)); | ||||
| 		} | ||||
|  | ||||
| 		// translation | ||||
| 		else if (!strcmp("TRAN", it->name)) | ||||
| 		{ | ||||
| 			float tmp_scale[3]; | ||||
| 			float tmp_rotation[4]; | ||||
| 			float tmp_trans[3]; | ||||
|  | ||||
| 			m_file.seekg(it->position); | ||||
|  | ||||
| 			// read in the data | ||||
| 			for (int i = 0; i < 3; i++) | ||||
| 				m_file.read(F2V(tmp_scale[i]), sizeof(float)); | ||||
|  | ||||
| 			for (int i = 0; i < 4; i++) | ||||
| 				m_file.read(F2V(tmp_rotation[i]), sizeof(float)); | ||||
|  | ||||
| 			for (int i = 0; i < 3; i++) | ||||
| 				m_file.read(F2V(tmp_trans[i]), sizeof(float)); | ||||
|  | ||||
| 			// modify the matrix | ||||
| 			dataDestination->m4x4Translation.scale(tmp_scale[0], tmp_scale[1], tmp_scale[2]); | ||||
| 			dataDestination->m4x4Translation.rotate(QQuaternion(tmp_rotation[3], tmp_rotation[0], tmp_rotation[1], tmp_rotation[2])); | ||||
| 			dataDestination->m4x4Translation.translate(tmp_trans[0], tmp_trans[1], tmp_trans[2]); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		// geometry data | ||||
| 		else if (!strcmp("GEOM", it->name)) | ||||
| 		{ | ||||
| 			// get all GEOM subchunks | ||||
| 			std::list<ChunkHeader*> tmp_geomChunks; | ||||
| 			loadChunks(tmp_geomChunks, it->position, it->size); | ||||
|  | ||||
| 			// evaluate GEOM subchunks | ||||
| 			analyseGeomChunks(dataDestination, tmp_geomChunks); | ||||
|  | ||||
| 			// clean up GEOM subchunks | ||||
| 			while (!tmp_geomChunks.empty()) | ||||
| 			{ | ||||
| 				ChunkHeader* cur = tmp_geomChunks.front(); | ||||
| 				tmp_geomChunks.pop_front(); | ||||
| 				delete cur; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MshFile::analyseGeomChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList) | ||||
| { | ||||
| 	for (auto& it : chunkList) | ||||
| 	{ | ||||
| 		// segment | ||||
| 		if (!strcmp("SEGM", it->name)) | ||||
| 		{ | ||||
| 			// get all SEGM subchunks | ||||
| 			std::list<ChunkHeader*> tmp_segmChunks; | ||||
| 			loadChunks(tmp_segmChunks, it->position, it->size); | ||||
|  | ||||
| 			// evaluate SEGM subchunks | ||||
| 			analyseSegmChunks(dataDestination, tmp_segmChunks); | ||||
|  | ||||
| 			// clean up SEGM subchunk | ||||
| 			while (!tmp_segmChunks.empty()) | ||||
| 			{ | ||||
| 				ChunkHeader* cur = tmp_segmChunks.front(); | ||||
| 				tmp_segmChunks.pop_front(); | ||||
| 				delete cur; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// cloth | ||||
| 		else if (!strcmp("CLTH", it->name)) | ||||
| 		{ | ||||
| 			// get all CLTH subchunks | ||||
| 			std::list<ChunkHeader*> tmp_clthChunks; | ||||
| 			loadChunks(tmp_clthChunks, it->position, it->size); | ||||
|  | ||||
| 			// evaluate CLTH subchunks | ||||
| 			analyseClthChunks(dataDestination, tmp_clthChunks); | ||||
|  | ||||
| 			// clean up CLTH subchunks | ||||
| 			while (!tmp_clthChunks.empty()) | ||||
| 			{ | ||||
| 				ChunkHeader* cur = tmp_clthChunks.front(); | ||||
| 				tmp_clthChunks.pop_front(); | ||||
| 				delete cur; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList) | ||||
| { | ||||
| 	Segment* new_segment = new Segment; | ||||
|  | ||||
| 	for (auto& it : chunkList) | ||||
| 	{ | ||||
| 		// material index | ||||
| 		if (!strcmp("MATI", it->name)) | ||||
| 		{ | ||||
| 			m_file.seekg(it->position); | ||||
| 			m_file.read(F2V(new_segment->textureIndex), sizeof(new_segment->textureIndex)); | ||||
| 		} | ||||
|  | ||||
| 		// position list (vertex) | ||||
| 		else if (!strcmp("POSL", it->name)) | ||||
| 		{ | ||||
| 			readVertex(new_segment, it->position); | ||||
| 		} | ||||
|  | ||||
| 		// normals | ||||
| 		/*else if (!strcmp("NRML", it->name)) | ||||
| 		{ | ||||
| 		fsMesh.seekg(it->position); | ||||
| 		std::uint32_t tempSize; | ||||
| 		fsMesh.read(reinterpret_cast<char*>(&tempSize), sizeof(tempSize)); | ||||
| 		// List of normals | ||||
| 		// long int - 4 - number of normal vectores stored in this list | ||||
| 		// float[3][] - 12 each - UVW vector for each vertex | ||||
| 		}*/ | ||||
|  | ||||
| 		// uv | ||||
| 		else if (!strcmp("UV0L", it->name)) | ||||
| 		{ | ||||
| 			readUV(new_segment, it->position); | ||||
| 		} | ||||
|  | ||||
| 		// polygons (indices into vertex/uv list) | ||||
| 		else if (!strcmp("STRP", it->name)) | ||||
| 		{ | ||||
| 			// don't get null, bone, shadowMesh and hidden mesh indices | ||||
| 			if (dataDestination->type == null || | ||||
| 				dataDestination->type == bone || | ||||
| 				dataDestination->type == shadowMesh || | ||||
| 				dataDestination->renderFlags == 1) | ||||
| 				continue; | ||||
|  | ||||
| 			// jump to the data section and read the size; | ||||
| 			std::uint32_t tmp_size; | ||||
| 			m_file.seekg(it->position); | ||||
| 			m_file.read(F2V(tmp_size), sizeof(tmp_size)); | ||||
|  | ||||
| 			int highBitCount(0); | ||||
| 			QVector<GLuint> tmp_buffer; | ||||
|  | ||||
| 			for (unsigned int i = 0; i < tmp_size; i++) | ||||
| 			{ | ||||
| 				// ReadData | ||||
| 				std::uint16_t tmp_value; | ||||
| 				m_file.read(F2V(tmp_value), sizeof(tmp_value)); | ||||
|  | ||||
| 				// Check if highbit is set | ||||
| 				if (tmp_value >> 15) | ||||
| 				{ | ||||
| 					highBitCount++; | ||||
| 					// remove the high bit, to get the actually value | ||||
| 					tmp_value = (std::uint16_t(tmp_value << 1) >> 1); | ||||
| 				} | ||||
|  | ||||
| 				// save data | ||||
| 				tmp_buffer.push_back((GLuint)tmp_value); | ||||
|  | ||||
| 				// if the last 2 highBits are set, it was a new poly | ||||
| 				if (highBitCount == 2) | ||||
| 				{ | ||||
| 					// reset highBitCount | ||||
| 					highBitCount = 0; | ||||
|  | ||||
| 					if (tmp_buffer.size() == 5) | ||||
| 					{ | ||||
| 						for (size_t i = 0; i < 3; i++) | ||||
| 							new_segment->indices.push_back(tmp_buffer.takeFirst()); | ||||
| 					} | ||||
| 					else if (tmp_buffer.size() > 5) | ||||
| 					{ | ||||
| 						unsigned int tmp_multiPolySize = tmp_buffer.size() - 2; | ||||
| 						// for every triangle of the multi polygon.. | ||||
| 						for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++) | ||||
| 							// ..calculate the edge indices | ||||
| 							for (int triEdge = 0; triEdge < 3; triEdge++) | ||||
| 								new_segment->indices.push_back((GLuint)(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						//TODO: this shouldn't happen only once | ||||
| 					} | ||||
|  | ||||
| 				}	// if 2 high bits are set | ||||
|  | ||||
| 			}	// for all values | ||||
|  | ||||
| 			// save the last polygon (no 2 high bit followed) | ||||
| 			if (tmp_buffer.size() == 3) | ||||
| 			{ | ||||
| 				for (size_t i = 0; i < 3; i++) | ||||
| 					new_segment->indices.push_back(tmp_buffer.takeFirst()); | ||||
| 			} | ||||
| 			else if (tmp_buffer.size() > 3) | ||||
| 			{ | ||||
| 				unsigned int tmp_multiPolySize = tmp_buffer.size(); | ||||
| 				// for every triangle of the multi polygon.. | ||||
| 				for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++) | ||||
| 					// ..calculate the edge indices | ||||
| 					for (int triEdge = 0; triEdge < 3; triEdge++) | ||||
| 						new_segment->indices.push_back((GLuint)(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				//TODO: this shouldn't happen | ||||
| 				std::cout << "Where am i??" << std::endl; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	dataDestination->segmList.push_back(new_segment); | ||||
| } | ||||
|  | ||||
| void MshFile::analyseClthChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList) | ||||
| { | ||||
| 	Segment* new_segment = new Segment; | ||||
|  | ||||
| 	for (auto& it : chunkList) | ||||
| 	{ | ||||
| 		// texture name | ||||
| 		if (!strcmp("CTEX", it->name)) | ||||
| 		{ | ||||
| 			// read the texture name | ||||
| 			m_file.seekg(it->position); | ||||
| 			char* buffer = new char[it->size + 1]; | ||||
| 			*buffer = { 0 }; | ||||
| 			m_file.read(buffer, it->size); | ||||
|  | ||||
| 			// search if it is already known | ||||
| 			bool tmp_found(false); | ||||
| 			for (unsigned int i = 0; i < m_textureNames->size(); i++) | ||||
| 			{ | ||||
| 				if (!strcmp(buffer, m_textureNames->at(i).c_str())) | ||||
| 				{ | ||||
| 					// if found, save the index and stop searching | ||||
| 					new_segment->textureIndex = i; | ||||
| 					tmp_found = true; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// if it was not found add the texturename to the list | ||||
| 			if (!tmp_found) | ||||
| 			{ | ||||
| 				m_textureNames->push_back(std::string(buffer)); | ||||
| 				new_segment->textureIndex = m_textureNames->size() - 1; | ||||
| 			} | ||||
|  | ||||
| 			delete[] buffer; | ||||
| 		} | ||||
|  | ||||
| 		// position list (vertex) | ||||
| 		else if (!strcmp("CPOS", it->name)) | ||||
| 		{ | ||||
| 			readVertex(new_segment, it->position); | ||||
| 		} | ||||
|  | ||||
| 		// uv  | ||||
| 		else if (!strcmp("CUV0", it->name)) | ||||
| 		{ | ||||
| 			readUV(new_segment, it->position); | ||||
| 		} | ||||
|  | ||||
| 		// triangles (indices into vertex/uv list) | ||||
| 		else if (!strcmp("CMSH", it->name)) | ||||
| 		{ | ||||
| 			// jump to the data section and read the size; | ||||
| 			std::uint32_t tmp_size; | ||||
| 			m_file.seekg(it->position); | ||||
| 			m_file.read(F2V(tmp_size), sizeof(tmp_size)); | ||||
|  | ||||
| 			// for every triangle.. | ||||
| 			for (unsigned int i = 0; i < tmp_size * 3; i++) | ||||
| 			{ | ||||
| 				std::uint32_t tmp_value; | ||||
| 				m_file.read(F2V(tmp_value), sizeof(std::uint32_t)); | ||||
|  | ||||
| 				new_segment->indices.push_back((GLuint)tmp_value); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	dataDestination->segmList.push_back(new_segment); | ||||
| } | ||||
|  | ||||
| void MshFile::readVertex(Segment * dataDestination, std::streampos position) | ||||
| { | ||||
| 	std::uint32_t tmp_size; | ||||
| 	m_file.seekg(position); | ||||
| 	m_file.read(F2V(tmp_size), sizeof(tmp_size)); | ||||
|  | ||||
| 	for (unsigned int i = 0; i < tmp_size; i++) | ||||
| 	{ | ||||
| 		float tmp[3]; | ||||
| 		for (unsigned int j = 0; j < 3; j++) | ||||
| 			m_file.read(F2V(tmp[j]), sizeof(float)); | ||||
| 		 | ||||
| 		VertexData new_data; | ||||
| 		new_data.position = QVector3D(tmp[0], tmp[1], tmp[2]); | ||||
|  | ||||
| 		dataDestination->vertices.push_back(new_data); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void MshFile::readUV(Segment * dataDestination, std::streampos position) | ||||
| { | ||||
| 	std::uint32_t tmp_size; | ||||
| 	m_file.seekg(position); | ||||
| 	m_file.read(F2V(tmp_size), sizeof(tmp_size)); | ||||
|  | ||||
| 	if (tmp_size < dataDestination->vertices.size()) | ||||
| 	{ | ||||
| 		//TODO: warning | ||||
| 		std::cout << "WARNING: too less UVs " << tmp_size << " < " << dataDestination->vertices.size() << std::endl; | ||||
|  | ||||
| 		//TODO: fill backward with default UVs | ||||
| 	} | ||||
| 	else if (tmp_size > dataDestination->vertices.size()) | ||||
| 	{ | ||||
| 		//TODO: warning | ||||
| 		std::cout << "WARNING: too many UVs " << tmp_size << " > " << dataDestination->vertices.size() << std::endl; | ||||
| 		tmp_size = dataDestination->vertices.size(); | ||||
| 	} | ||||
|  | ||||
| 	for (unsigned int i = 0; i < tmp_size; i++) | ||||
| 	{ | ||||
| 		float tmp[2]; | ||||
| 		for (unsigned int j = 0; j < 2; j++) | ||||
| 			m_file.read(F2V(dataDestination->vertices[i].texCoord[j]), sizeof(float)); | ||||
| 	} | ||||
| } | ||||
| @@ -1,7 +1,6 @@ | ||||
| #include "Header\MainWindow.h" | ||||
| #include <QtWidgets/QApplication> | ||||
|  | ||||
|  | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| 	QApplication a(argc, argv); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Anakin
					Anakin