diff options
Diffstat (limited to 'src/3rdparty/assimp/code/Q3DLoader.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/Q3DLoader.cpp | 1073 |
1 files changed, 538 insertions, 535 deletions
diff --git a/src/3rdparty/assimp/code/Q3DLoader.cpp b/src/3rdparty/assimp/code/Q3DLoader.cpp index 0e436e328..d9dc29672 100644 --- a/src/3rdparty/assimp/code/Q3DLoader.cpp +++ b/src/3rdparty/assimp/code/Q3DLoader.cpp @@ -3,12 +3,12 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2012, assimp team +Copyright (c) 2006-2016, assimp team All rights reserved. -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above @@ -25,16 +25,16 @@ conditions are met: derived from this software without specific prior written permission of the assimp team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ @@ -43,27 +43,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the Q3D importer class */ -#include "AssimpPCH.h" + #ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER // internal headers #include "Q3DLoader.h" #include "StreamReader.h" #include "fast_atof.h" +#include <assimp/IOSystem.hpp> +#include <assimp/DefaultLogger.hpp> +#include <assimp/scene.h> using namespace Assimp; static const aiImporterDesc desc = { - "Quick3D Importer", - "", - "", - "http://www.quick3d.com/", - aiImporterFlags_SupportBinaryFlavour, - 0, - 0, - 0, - 0, - "q3o q3s" + "Quick3D Importer", + "", + "", + "http://www.quick3d.com/", + aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, + "q3o q3s" }; // ------------------------------------------------------------------------------------------------ @@ -72,540 +75,540 @@ Q3DImporter::Q3DImporter() {} // ------------------------------------------------------------------------------------------------ -// Destructor, private as well +// Destructor, private as well Q3DImporter::~Q3DImporter() {} // ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. +// Returns whether the class can handle the format of the given file. bool Q3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - - if (extension == "q3s" || extension == "q3o") - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) - return true; - const char* tokens[] = {"quick3Do","quick3Ds"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); - } - return false; + const std::string extension = GetExtension(pFile); + + if (extension == "q3s" || extension == "q3o") + return true; + else if (!extension.length() || checkSig) { + if (!pIOHandler) + return true; + const char* tokens[] = {"quick3Do","quick3Ds"}; + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); + } + return false; } // ------------------------------------------------------------------------------------------------ const aiImporterDesc* Q3DImporter::GetInfo () const { - return &desc; + return &desc; } // ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void Q3DImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) +// Imports the given file into the given scene structure. +void Q3DImporter::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) { - StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); - - // The header is 22 bytes large - if (stream.GetRemainingSize() < 22) - throw DeadlyImportError("File is either empty or corrupt: " + pFile); - - // Check the file's signature - if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) && - ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 )) - { - throw DeadlyImportError("Not a Quick3D file. Signature string is: " + - std::string((const char*)stream.GetPtr(),8)); - } - - // Print the file format version - DefaultLogger::get()->info("Quick3D File format version: " + - std::string(&((const char*)stream.GetPtr())[8],2)); - - // ... an store it - char major = ((const char*)stream.GetPtr())[8]; - char minor = ((const char*)stream.GetPtr())[9]; - - stream.IncPtr(10); - unsigned int numMeshes = (unsigned int)stream.GetI4(); - unsigned int numMats = (unsigned int)stream.GetI4(); - unsigned int numTextures = (unsigned int)stream.GetI4(); - - std::vector<Material> materials; - materials.reserve(numMats); - - std::vector<Mesh> meshes; - meshes.reserve(numMeshes); - - // Allocate the scene root node - pScene->mRootNode = new aiNode(); - - aiColor3D fgColor (0.6f,0.6f,0.6f); - - // Now read all file chunks - while (true) - { - if (stream.GetRemainingSize() < 1)break; - char c = stream.GetI1(); - switch (c) - { - // Meshes chunk - case 'm': - { - for (unsigned int quak = 0; quak < numMeshes; ++quak) - { - meshes.push_back(Mesh()); - Mesh& mesh = meshes.back(); - - // read all vertices - unsigned int numVerts = (unsigned int)stream.GetI4(); - if (!numVerts) - throw DeadlyImportError("Quick3D: Found mesh with zero vertices"); - - std::vector<aiVector3D>& verts = mesh.verts; - verts.resize(numVerts); - - for (unsigned int i = 0; i < numVerts;++i) - { - verts[i].x = stream.GetF4(); - verts[i].y = stream.GetF4(); - verts[i].z = stream.GetF4(); - } - - // read all faces - numVerts = (unsigned int)stream.GetI4(); - if (!numVerts) - throw DeadlyImportError("Quick3D: Found mesh with zero faces"); - - std::vector<Face >& faces = mesh.faces; - faces.reserve(numVerts); - - // number of indices - for (unsigned int i = 0; i < numVerts;++i) - { - faces.push_back(Face(stream.GetI2()) ); - if (faces.back().indices.empty()) - throw DeadlyImportError("Quick3D: Found face with zero indices"); - } - - // indices - for (unsigned int i = 0; i < numVerts;++i) - { - Face& vec = faces[i]; - for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a) - vec.indices[a] = stream.GetI4(); - } - - // material indices - for (unsigned int i = 0; i < numVerts;++i) - { - faces[i].mat = (unsigned int)stream.GetI4(); - } - - // read all normals - numVerts = (unsigned int)stream.GetI4(); - std::vector<aiVector3D>& normals = mesh.normals; - normals.resize(numVerts); - - for (unsigned int i = 0; i < numVerts;++i) - { - normals[i].x = stream.GetF4(); - normals[i].y = stream.GetF4(); - normals[i].z = stream.GetF4(); - } - - numVerts = (unsigned int)stream.GetI4(); - if (numTextures && numVerts) - { - // read all texture coordinates - std::vector<aiVector3D>& uv = mesh.uv; - uv.resize(numVerts); - - for (unsigned int i = 0; i < numVerts;++i) - { - uv[i].x = stream.GetF4(); - uv[i].y = stream.GetF4(); - } - - // UV indices - for (unsigned int i = 0; i < (unsigned int)faces.size();++i) - { - Face& vec = faces[i]; - for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a) - { - vec.uvindices[a] = stream.GetI4(); - if (!i && !a) - mesh.prevUVIdx = vec.uvindices[a]; - else if (vec.uvindices[a] != mesh.prevUVIdx) - mesh.prevUVIdx = UINT_MAX; - } - } - } - - // we don't need the rest, but we need to get to the next chunk - stream.IncPtr(36); - if (minor > '0' && major == '3') - stream.IncPtr(mesh.faces.size()); - } - // stream.IncPtr(4); // unknown value here - } - break; - - // materials chunk - case 'c': - - for (unsigned int i = 0; i < numMats; ++i) - { - materials.push_back(Material()); - Material& mat = materials.back(); - - // read the material name - while (( c = stream.GetI1())) - mat.name.data[mat.name.length++] = c; - - // add the terminal character - mat.name.data[mat.name.length] = '\0'; - - // read the ambient color - mat.ambient.r = stream.GetF4(); - mat.ambient.g = stream.GetF4(); - mat.ambient.b = stream.GetF4(); - - // read the diffuse color - mat.diffuse.r = stream.GetF4(); - mat.diffuse.g = stream.GetF4(); - mat.diffuse.b = stream.GetF4(); - - // read the ambient color - mat.specular.r = stream.GetF4(); - mat.specular.g = stream.GetF4(); - mat.specular.b = stream.GetF4(); - - // read the transparency - mat.transparency = stream.GetF4(); - - // unknown value here - // stream.IncPtr(4); - // FIX: it could be the texture index ... - mat.texIdx = (unsigned int)stream.GetI4(); - } - - break; - - // texture chunk - case 't': - - pScene->mNumTextures = numTextures; - if (!numTextures)break; - pScene->mTextures = new aiTexture*[pScene->mNumTextures]; - // to make sure we won't crash if we leave through an exception - ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures); - for (unsigned int i = 0; i < pScene->mNumTextures; ++i) - { - aiTexture* tex = pScene->mTextures[i] = new aiTexture(); - - // skip the texture name - while (stream.GetI1()); - - // read texture width and height - tex->mWidth = (unsigned int)stream.GetI4(); - tex->mHeight = (unsigned int)stream.GetI4(); - - if (!tex->mWidth || !tex->mHeight) - throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero"); - - unsigned int mul = tex->mWidth * tex->mHeight; - aiTexel* begin = tex->pcData = new aiTexel[mul]; - aiTexel* const end = & begin [mul]; - - for (;begin != end; ++begin) - { - begin->r = stream.GetI1(); - begin->g = stream.GetI1(); - begin->b = stream.GetI1(); - begin->a = 0xff; - } - } - - break; - - // scene chunk - case 's': - { - // skip position and rotation - stream.IncPtr(12); - - for (unsigned int i = 0; i < 4;++i) - for (unsigned int a = 0; a < 4;++a) - pScene->mRootNode->mTransformation[i][a] = stream.GetF4(); - - stream.IncPtr(16); - - // now setup a single camera - pScene->mNumCameras = 1; - pScene->mCameras = new aiCamera*[1]; - aiCamera* cam = pScene->mCameras[0] = new aiCamera(); - cam->mPosition.x = stream.GetF4(); - cam->mPosition.y = stream.GetF4(); - cam->mPosition.z = stream.GetF4(); - cam->mName.Set("Q3DCamera"); - - // skip eye rotation for the moment - stream.IncPtr(12); - - // read the default material color - fgColor .r = stream.GetF4(); - fgColor .g = stream.GetF4(); - fgColor .b = stream.GetF4(); - - // skip some unimportant properties - stream.IncPtr(29); - - // setup a single point light with no attenuation - pScene->mNumLights = 1; - pScene->mLights = new aiLight*[1]; - aiLight* light = pScene->mLights[0] = new aiLight(); - light->mName.Set("Q3DLight"); - light->mType = aiLightSource_POINT; - - light->mAttenuationConstant = 1; - light->mAttenuationLinear = 0; - light->mAttenuationQuadratic = 0; - - light->mColorDiffuse.r = stream.GetF4(); - light->mColorDiffuse.g = stream.GetF4(); - light->mColorDiffuse.b = stream.GetF4(); - - light->mColorSpecular = light->mColorDiffuse; - - - // We don't need the rest, but we need to know where this chunk ends. - unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4()); - - // skip the background file name - while (stream.GetI1()); - - // skip background texture data + the remaining fields - stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here - - // TODO - goto outer; - } - break; - - default: - throw DeadlyImportError("Quick3D: Unknown chunk"); - break; - }; - } + StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); + + // The header is 22 bytes large + if (stream.GetRemainingSize() < 22) + throw DeadlyImportError("File is either empty or corrupt: " + pFile); + + // Check the file's signature + if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) && + ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 )) + { + throw DeadlyImportError("Not a Quick3D file. Signature string is: " + + std::string((const char*)stream.GetPtr(),8)); + } + + // Print the file format version + DefaultLogger::get()->info("Quick3D File format version: " + + std::string(&((const char*)stream.GetPtr())[8],2)); + + // ... an store it + char major = ((const char*)stream.GetPtr())[8]; + char minor = ((const char*)stream.GetPtr())[9]; + + stream.IncPtr(10); + unsigned int numMeshes = (unsigned int)stream.GetI4(); + unsigned int numMats = (unsigned int)stream.GetI4(); + unsigned int numTextures = (unsigned int)stream.GetI4(); + + std::vector<Material> materials; + materials.reserve(numMats); + + std::vector<Mesh> meshes; + meshes.reserve(numMeshes); + + // Allocate the scene root node + pScene->mRootNode = new aiNode(); + + aiColor3D fgColor (0.6f,0.6f,0.6f); + + // Now read all file chunks + while (true) + { + if (stream.GetRemainingSize() < 1)break; + char c = stream.GetI1(); + switch (c) + { + // Meshes chunk + case 'm': + { + for (unsigned int quak = 0; quak < numMeshes; ++quak) + { + meshes.push_back(Mesh()); + Mesh& mesh = meshes.back(); + + // read all vertices + unsigned int numVerts = (unsigned int)stream.GetI4(); + if (!numVerts) + throw DeadlyImportError("Quick3D: Found mesh with zero vertices"); + + std::vector<aiVector3D>& verts = mesh.verts; + verts.resize(numVerts); + + for (unsigned int i = 0; i < numVerts;++i) + { + verts[i].x = stream.GetF4(); + verts[i].y = stream.GetF4(); + verts[i].z = stream.GetF4(); + } + + // read all faces + numVerts = (unsigned int)stream.GetI4(); + if (!numVerts) + throw DeadlyImportError("Quick3D: Found mesh with zero faces"); + + std::vector<Face >& faces = mesh.faces; + faces.reserve(numVerts); + + // number of indices + for (unsigned int i = 0; i < numVerts;++i) + { + faces.push_back(Face(stream.GetI2()) ); + if (faces.back().indices.empty()) + throw DeadlyImportError("Quick3D: Found face with zero indices"); + } + + // indices + for (unsigned int i = 0; i < numVerts;++i) + { + Face& vec = faces[i]; + for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a) + vec.indices[a] = stream.GetI4(); + } + + // material indices + for (unsigned int i = 0; i < numVerts;++i) + { + faces[i].mat = (unsigned int)stream.GetI4(); + } + + // read all normals + numVerts = (unsigned int)stream.GetI4(); + std::vector<aiVector3D>& normals = mesh.normals; + normals.resize(numVerts); + + for (unsigned int i = 0; i < numVerts;++i) + { + normals[i].x = stream.GetF4(); + normals[i].y = stream.GetF4(); + normals[i].z = stream.GetF4(); + } + + numVerts = (unsigned int)stream.GetI4(); + if (numTextures && numVerts) + { + // read all texture coordinates + std::vector<aiVector3D>& uv = mesh.uv; + uv.resize(numVerts); + + for (unsigned int i = 0; i < numVerts;++i) + { + uv[i].x = stream.GetF4(); + uv[i].y = stream.GetF4(); + } + + // UV indices + for (unsigned int i = 0; i < (unsigned int)faces.size();++i) + { + Face& vec = faces[i]; + for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a) + { + vec.uvindices[a] = stream.GetI4(); + if (!i && !a) + mesh.prevUVIdx = vec.uvindices[a]; + else if (vec.uvindices[a] != mesh.prevUVIdx) + mesh.prevUVIdx = UINT_MAX; + } + } + } + + // we don't need the rest, but we need to get to the next chunk + stream.IncPtr(36); + if (minor > '0' && major == '3') + stream.IncPtr(mesh.faces.size()); + } + // stream.IncPtr(4); // unknown value here + } + break; + + // materials chunk + case 'c': + + for (unsigned int i = 0; i < numMats; ++i) + { + materials.push_back(Material()); + Material& mat = materials.back(); + + // read the material name + while (( c = stream.GetI1())) + mat.name.data[mat.name.length++] = c; + + // add the terminal character + mat.name.data[mat.name.length] = '\0'; + + // read the ambient color + mat.ambient.r = stream.GetF4(); + mat.ambient.g = stream.GetF4(); + mat.ambient.b = stream.GetF4(); + + // read the diffuse color + mat.diffuse.r = stream.GetF4(); + mat.diffuse.g = stream.GetF4(); + mat.diffuse.b = stream.GetF4(); + + // read the ambient color + mat.specular.r = stream.GetF4(); + mat.specular.g = stream.GetF4(); + mat.specular.b = stream.GetF4(); + + // read the transparency + mat.transparency = stream.GetF4(); + + // unknown value here + // stream.IncPtr(4); + // FIX: it could be the texture index ... + mat.texIdx = (unsigned int)stream.GetI4(); + } + + break; + + // texture chunk + case 't': + + pScene->mNumTextures = numTextures; + if (!numTextures)break; + pScene->mTextures = new aiTexture*[pScene->mNumTextures]; + // to make sure we won't crash if we leave through an exception + ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures); + for (unsigned int i = 0; i < pScene->mNumTextures; ++i) + { + aiTexture* tex = pScene->mTextures[i] = new aiTexture(); + + // skip the texture name + while (stream.GetI1()); + + // read texture width and height + tex->mWidth = (unsigned int)stream.GetI4(); + tex->mHeight = (unsigned int)stream.GetI4(); + + if (!tex->mWidth || !tex->mHeight) + throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero"); + + unsigned int mul = tex->mWidth * tex->mHeight; + aiTexel* begin = tex->pcData = new aiTexel[mul]; + aiTexel* const end = & begin [mul]; + + for (;begin != end; ++begin) + { + begin->r = stream.GetI1(); + begin->g = stream.GetI1(); + begin->b = stream.GetI1(); + begin->a = 0xff; + } + } + + break; + + // scene chunk + case 's': + { + // skip position and rotation + stream.IncPtr(12); + + for (unsigned int i = 0; i < 4;++i) + for (unsigned int a = 0; a < 4;++a) + pScene->mRootNode->mTransformation[i][a] = stream.GetF4(); + + stream.IncPtr(16); + + // now setup a single camera + pScene->mNumCameras = 1; + pScene->mCameras = new aiCamera*[1]; + aiCamera* cam = pScene->mCameras[0] = new aiCamera(); + cam->mPosition.x = stream.GetF4(); + cam->mPosition.y = stream.GetF4(); + cam->mPosition.z = stream.GetF4(); + cam->mName.Set("Q3DCamera"); + + // skip eye rotation for the moment + stream.IncPtr(12); + + // read the default material color + fgColor .r = stream.GetF4(); + fgColor .g = stream.GetF4(); + fgColor .b = stream.GetF4(); + + // skip some unimportant properties + stream.IncPtr(29); + + // setup a single point light with no attenuation + pScene->mNumLights = 1; + pScene->mLights = new aiLight*[1]; + aiLight* light = pScene->mLights[0] = new aiLight(); + light->mName.Set("Q3DLight"); + light->mType = aiLightSource_POINT; + + light->mAttenuationConstant = 1; + light->mAttenuationLinear = 0; + light->mAttenuationQuadratic = 0; + + light->mColorDiffuse.r = stream.GetF4(); + light->mColorDiffuse.g = stream.GetF4(); + light->mColorDiffuse.b = stream.GetF4(); + + light->mColorSpecular = light->mColorDiffuse; + + + // We don't need the rest, but we need to know where this chunk ends. + unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4()); + + // skip the background file name + while (stream.GetI1()); + + // skip background texture data + the remaining fields + stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here + + // TODO + goto outer; + } + break; + + default: + throw DeadlyImportError("Quick3D: Unknown chunk"); + break; + }; + } outer: - // If we have no mesh loaded - break here - if (meshes.empty()) - throw DeadlyImportError("Quick3D: No meshes loaded"); - - // If we have no materials loaded - generate a default mat - if (materials.empty()) - { - DefaultLogger::get()->info("Quick3D: No material found, generating one"); - materials.push_back(Material()); - materials.back().diffuse = fgColor ; - } - - // find out which materials we'll need - typedef std::pair<unsigned int, unsigned int> FaceIdx; - typedef std::vector< FaceIdx > FaceIdxArray; - FaceIdxArray* fidx = new FaceIdxArray[materials.size()]; - - unsigned int p = 0; - for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end(); - it != end; ++it,++p) - { - unsigned int q = 0; - for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end(); - fit != fend; ++fit,++q) - { - if ((*fit).mat >= materials.size()) - { - DefaultLogger::get()->warn("Quick3D: Material index overflow"); - (*fit).mat = 0; - } - if (fidx[(*fit).mat].empty())++pScene->mNumMeshes; - fidx[(*fit).mat].push_back( FaceIdx(p,q) ); - } - } - pScene->mNumMaterials = pScene->mNumMeshes; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - pScene->mMeshes = new aiMesh*[pScene->mNumMaterials]; - - for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) - { - if (fidx[i].empty())continue; - - // Allocate a mesh and a material - aiMesh* mesh = pScene->mMeshes[real] = new aiMesh(); - aiMaterial* mat = new aiMaterial(); - pScene->mMaterials[real] = mat; - - mesh->mMaterialIndex = real; - - // Build the output material - Material& srcMat = materials[i]; - mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR); - mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT); - - // NOTE: Ignore transparency for the moment - it seems - // unclear how to interpret the data + // If we have no mesh loaded - break here + if (meshes.empty()) + throw DeadlyImportError("Quick3D: No meshes loaded"); + + // If we have no materials loaded - generate a default mat + if (materials.empty()) + { + DefaultLogger::get()->info("Quick3D: No material found, generating one"); + materials.push_back(Material()); + materials.back().diffuse = fgColor ; + } + + // find out which materials we'll need + typedef std::pair<unsigned int, unsigned int> FaceIdx; + typedef std::vector< FaceIdx > FaceIdxArray; + FaceIdxArray* fidx = new FaceIdxArray[materials.size()]; + + unsigned int p = 0; + for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end(); + it != end; ++it,++p) + { + unsigned int q = 0; + for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end(); + fit != fend; ++fit,++q) + { + if ((*fit).mat >= materials.size()) + { + DefaultLogger::get()->warn("Quick3D: Material index overflow"); + (*fit).mat = 0; + } + if (fidx[(*fit).mat].empty())++pScene->mNumMeshes; + fidx[(*fit).mat].push_back( FaceIdx(p,q) ); + } + } + pScene->mNumMaterials = pScene->mNumMeshes; + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + pScene->mMeshes = new aiMesh*[pScene->mNumMaterials]; + + for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) + { + if (fidx[i].empty())continue; + + // Allocate a mesh and a material + aiMesh* mesh = pScene->mMeshes[real] = new aiMesh(); + aiMaterial* mat = new aiMaterial(); + pScene->mMaterials[real] = mat; + + mesh->mMaterialIndex = real; + + // Build the output material + Material& srcMat = materials[i]; + mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR); + mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT); + + // NOTE: Ignore transparency for the moment - it seems + // unclear how to interpret the data #if 0 - if (!(minor > '0' && major == '3')) - srcMat.transparency = 1.0f - srcMat.transparency; - mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY); + if (!(minor > '0' && major == '3')) + srcMat.transparency = 1.0f - srcMat.transparency; + mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY); #endif - // add shininess - Quick3D seems to use it ins its viewer - srcMat.transparency = 16.f; - mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_SHININESS); - - int m = (int)aiShadingMode_Phong; - mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL); - - if (srcMat.name.length) - mat->AddProperty(&srcMat.name,AI_MATKEY_NAME); - - // Add a texture - if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures) - { - srcMat.name.data[0] = '*'; - srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000, - (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real)); - mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - - mesh->mNumFaces = (unsigned int)fidx[i].size(); - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; - - // Now build the output mesh. First find out how many - // vertices we'll need - for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); - it != end; ++it) - { - mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[ - (*it).second].indices.size(); - } - - aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - aiVector3D* uv; - if (real < pScene->mNumTextures) - { - uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - mesh->mNumUVComponents[0] = 2; - } - else uv = NULL; - - // Build the final array - unsigned int cnt = 0; - for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); - it != end; ++it, ++faces) - { - Mesh& m = meshes[(*it).first]; - Face& face = m.faces[(*it).second]; - faces->mNumIndices = (unsigned int)face.indices.size(); - faces->mIndices = new unsigned int [faces->mNumIndices]; - - - aiVector3D faceNormal; - bool fnOK = false; - - for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts) - { - if (face.indices[n] >= m.verts.size()) - { - DefaultLogger::get()->warn("Quick3D: Vertex index overflow"); - face.indices[n] = 0; - } - - // copy vertices - *verts = m.verts[ face.indices[n] ]; - - if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3) - { - // we have no normal here - assign the face normal - if (!fnOK) - { - const aiVector3D& pV1 = m.verts[ face.indices[0] ]; - const aiVector3D& pV2 = m.verts[ face.indices[1] ]; - const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ]; - faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize(); - fnOK = true; - } - *norms = faceNormal; - } - else *norms = m.normals[ face.indices[n] ]; - - // copy texture coordinates - if (uv && m.uv.size()) - { - if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround - { - *uv = m.uv[face.indices[n]]; - } - else - { - if (face.uvindices[n] >= m.uv.size()) - { - DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow"); - face.uvindices[n] = 0; - } - *uv = m.uv[face.uvindices[n]]; - } - uv->y = 1.f - uv->y; - ++uv; - } - - // setup the new vertex index - faces->mIndices[n] = cnt; - } - - } - ++real; - } - - // Delete our nice helper array - delete[] fidx; - - // Now we need to attach the meshes to the root node of the scene - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mRootNode->mMeshes[i] = i; - - /*pScene->mRootNode->mTransformation *= aiMatrix4x4( - 1.f, 0.f, 0.f, 0.f, - 0.f, -1.f,0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f);*/ - - // Add cameras and light sources to the scene root node - pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras; - if (pScene->mRootNode->mNumChildren) - { - pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ]; - - // the light source - aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode(); - nd->mParent = pScene->mRootNode; - nd->mName.Set("Q3DLight"); - nd->mTransformation = pScene->mRootNode->mTransformation; - nd->mTransformation.Inverse(); - - // camera - nd = pScene->mRootNode->mChildren[1] = new aiNode(); - nd->mParent = pScene->mRootNode; - nd->mName.Set("Q3DCamera"); - nd->mTransformation = pScene->mRootNode->mChildren[0]->mTransformation; - } + // add shininess - Quick3D seems to use it ins its viewer + srcMat.transparency = 16.f; + mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_SHININESS); + + int m = (int)aiShadingMode_Phong; + mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL); + + if (srcMat.name.length) + mat->AddProperty(&srcMat.name,AI_MATKEY_NAME); + + // Add a texture + if (srcMat.texIdx < pScene->mNumTextures || real < pScene->mNumTextures) + { + srcMat.name.data[0] = '*'; + srcMat.name.length = ASSIMP_itoa10(&srcMat.name.data[1],1000, + (srcMat.texIdx < pScene->mNumTextures ? srcMat.texIdx : real)); + mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + + mesh->mNumFaces = (unsigned int)fidx[i].size(); + aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; + + // Now build the output mesh. First find out how many + // vertices we'll need + for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); + it != end; ++it) + { + mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[ + (*it).second].indices.size(); + } + + aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + aiVector3D* norms = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + aiVector3D* uv; + if (real < pScene->mNumTextures) + { + uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; + mesh->mNumUVComponents[0] = 2; + } + else uv = NULL; + + // Build the final array + unsigned int cnt = 0; + for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); + it != end; ++it, ++faces) + { + Mesh& m = meshes[(*it).first]; + Face& face = m.faces[(*it).second]; + faces->mNumIndices = (unsigned int)face.indices.size(); + faces->mIndices = new unsigned int [faces->mNumIndices]; + + + aiVector3D faceNormal; + bool fnOK = false; + + for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts) + { + if (face.indices[n] >= m.verts.size()) + { + DefaultLogger::get()->warn("Quick3D: Vertex index overflow"); + face.indices[n] = 0; + } + + // copy vertices + *verts = m.verts[ face.indices[n] ]; + + if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3) + { + // we have no normal here - assign the face normal + if (!fnOK) + { + const aiVector3D& pV1 = m.verts[ face.indices[0] ]; + const aiVector3D& pV2 = m.verts[ face.indices[1] ]; + const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ]; + faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize(); + fnOK = true; + } + *norms = faceNormal; + } + else *norms = m.normals[ face.indices[n] ]; + + // copy texture coordinates + if (uv && m.uv.size()) + { + if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround + { + *uv = m.uv[face.indices[n]]; + } + else + { + if (face.uvindices[n] >= m.uv.size()) + { + DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow"); + face.uvindices[n] = 0; + } + *uv = m.uv[face.uvindices[n]]; + } + uv->y = 1.f - uv->y; + ++uv; + } + + // setup the new vertex index + faces->mIndices[n] = cnt; + } + + } + ++real; + } + + // Delete our nice helper array + delete[] fidx; + + // Now we need to attach the meshes to the root node of the scene + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + pScene->mRootNode->mMeshes[i] = i; + + /*pScene->mRootNode->mTransformation *= aiMatrix4x4( + 1.f, 0.f, 0.f, 0.f, + 0.f, -1.f,0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f);*/ + + // Add cameras and light sources to the scene root node + pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras; + if (pScene->mRootNode->mNumChildren) + { + pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ]; + + // the light source + aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode(); + nd->mParent = pScene->mRootNode; + nd->mName.Set("Q3DLight"); + nd->mTransformation = pScene->mRootNode->mTransformation; + nd->mTransformation.Inverse(); + + // camera + nd = pScene->mRootNode->mChildren[1] = new aiNode(); + nd->mParent = pScene->mRootNode; + nd->mName.Set("Q3DCamera"); + nd->mTransformation = pScene->mRootNode->mChildren[0]->mTransformation; + } } #endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER |