nuclear@0: /* nuclear@0: --------------------------------------------------------------------------- nuclear@0: Open Asset Import Library (assimp) nuclear@0: --------------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the following nuclear@0: conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: --------------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file RawLoader.cpp nuclear@0: * @brief Implementation of the RAW importer class nuclear@0: */ nuclear@0: nuclear@0: #include "AssimpPCH.h" nuclear@0: #ifndef ASSIMP_BUILD_NO_RAW_IMPORTER nuclear@0: nuclear@0: // internal headers nuclear@0: #include "RawLoader.h" nuclear@0: #include "ParsingUtils.h" nuclear@0: #include "fast_atof.h" nuclear@0: nuclear@0: using namespace Assimp; nuclear@0: nuclear@0: static const aiImporterDesc desc = { nuclear@0: "Raw Importer", nuclear@0: "", nuclear@0: "", nuclear@0: "", nuclear@0: aiImporterFlags_SupportTextFlavour, nuclear@0: 0, nuclear@0: 0, nuclear@0: 0, nuclear@0: 0, nuclear@0: "raw" nuclear@0: }; nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Constructor to be privately used by Importer nuclear@0: RAWImporter::RAWImporter() nuclear@0: {} nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Destructor, private as well nuclear@0: RAWImporter::~RAWImporter() nuclear@0: {} nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Returns whether the class can handle the format of the given file. nuclear@0: bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const nuclear@0: { nuclear@0: return SimpleExtensionCheck(pFile,"raw"); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: const aiImporterDesc* RAWImporter::GetInfo () const nuclear@0: { nuclear@0: return &desc; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Imports the given file into the given scene structure. nuclear@0: void RAWImporter::InternReadFile( const std::string& pFile, nuclear@0: aiScene* pScene, IOSystem* pIOHandler) nuclear@0: { nuclear@0: boost::scoped_ptr file( pIOHandler->Open( pFile, "rb")); nuclear@0: nuclear@0: // Check whether we can read from the file nuclear@0: if( file.get() == NULL) { nuclear@0: throw DeadlyImportError( "Failed to open RAW file " + pFile + "."); nuclear@0: } nuclear@0: nuclear@0: // allocate storage and copy the contents of the file to a memory buffer nuclear@0: // (terminate it with zero) nuclear@0: std::vector mBuffer2; nuclear@0: TextFileToBuffer(file.get(),mBuffer2); nuclear@0: const char* buffer = &mBuffer2[0]; nuclear@0: nuclear@0: // list of groups loaded from the file nuclear@0: std::vector< GroupInformation > outGroups(1,GroupInformation("")); nuclear@0: std::vector< GroupInformation >::iterator curGroup = outGroups.begin(); nuclear@0: nuclear@0: // now read all lines nuclear@0: char line[4096]; nuclear@0: while (GetNextLine(buffer,line)) nuclear@0: { nuclear@0: // if the line starts with a non-numeric identifier, it marks nuclear@0: // the beginning of a new group nuclear@0: const char* sz = line;SkipSpaces(&sz); nuclear@0: if (IsLineEnd(*sz))continue; nuclear@0: if (!IsNumeric(*sz)) nuclear@0: { nuclear@0: const char* sz2 = sz; nuclear@0: while (!IsSpaceOrNewLine(*sz2))++sz2; nuclear@0: const unsigned int length = (unsigned int)(sz2-sz); nuclear@0: nuclear@0: // find an existing group with this name nuclear@0: for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); nuclear@0: it != end;++it) nuclear@0: { nuclear@0: if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str())) nuclear@0: { nuclear@0: curGroup = it;sz2 = NULL; nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: if (sz2) nuclear@0: { nuclear@0: outGroups.push_back(GroupInformation(std::string(sz,length))); nuclear@0: curGroup = outGroups.end()-1; nuclear@0: } nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: // there can be maximally 12 floats plus an extra texture file name nuclear@0: float data[12]; nuclear@0: unsigned int num; nuclear@0: for (num = 0; num < 12;++num) nuclear@0: { nuclear@0: if(!SkipSpaces(&sz) || !IsNumeric(*sz))break; nuclear@0: sz = fast_atoreal_move(sz,data[num]); nuclear@0: } nuclear@0: if (num != 12 && num != 9) nuclear@0: { nuclear@0: DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture"); nuclear@0: continue; nuclear@0: } nuclear@0: nuclear@0: MeshInformation* output = NULL; nuclear@0: nuclear@0: const char* sz2 = sz; nuclear@0: unsigned int length; nuclear@0: if (!IsLineEnd(*sz)) nuclear@0: { nuclear@0: while (!IsSpaceOrNewLine(*sz2))++sz2; nuclear@0: length = (unsigned int)(sz2-sz); nuclear@0: } nuclear@0: else if (9 == num) nuclear@0: { nuclear@0: sz = "%default%"; nuclear@0: length = 9; nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: sz = ""; nuclear@0: length = 0; nuclear@0: } nuclear@0: nuclear@0: // search in the list of meshes whether we have one with this texture nuclear@0: for (std::vector< MeshInformation >::iterator it = (*curGroup).meshes.begin(), nuclear@0: end = (*curGroup).meshes.end(); it != end; ++it) nuclear@0: { nuclear@0: if (length == (*it).name.length() && (length ? !::strcmp(sz,(*it).name.c_str()) : true)) nuclear@0: { nuclear@0: output = &(*it); nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: // if we don't have the mesh, create it nuclear@0: if (!output) nuclear@0: { nuclear@0: (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length))); nuclear@0: output = &((*curGroup).meshes.back()); nuclear@0: } nuclear@0: if (12 == num) nuclear@0: { nuclear@0: aiColor4D v(data[0],data[1],data[2],1.0f); nuclear@0: output->colors.push_back(v); nuclear@0: output->colors.push_back(v); nuclear@0: output->colors.push_back(v); nuclear@0: nuclear@0: output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); nuclear@0: output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); nuclear@0: output->vertices.push_back(aiVector3D(data[9],data[10],data[11])); nuclear@0: } nuclear@0: else nuclear@0: { nuclear@0: output->vertices.push_back(aiVector3D(data[0],data[1],data[2])); nuclear@0: output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); nuclear@0: output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: pScene->mRootNode = new aiNode(); nuclear@0: pScene->mRootNode->mName.Set(""); nuclear@0: nuclear@0: // count the number of valid groups nuclear@0: // (meshes can't be empty) nuclear@0: for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); nuclear@0: it != end;++it) nuclear@0: { nuclear@0: if (!(*it).meshes.empty()) nuclear@0: { nuclear@0: ++pScene->mRootNode->mNumChildren; nuclear@0: pScene->mNumMeshes += (unsigned int)(*it).meshes.size(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: if (!pScene->mNumMeshes) nuclear@0: { nuclear@0: throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty."); nuclear@0: } nuclear@0: nuclear@0: pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; nuclear@0: aiNode** cc; nuclear@0: if (1 == pScene->mRootNode->mNumChildren) nuclear@0: { nuclear@0: cc = &pScene->mRootNode; nuclear@0: pScene->mRootNode->mNumChildren = 0; nuclear@0: } nuclear@0: else cc = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; nuclear@0: nuclear@0: pScene->mNumMaterials = pScene->mNumMeshes; nuclear@0: aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; nuclear@0: nuclear@0: unsigned int meshIdx = 0; nuclear@0: for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); nuclear@0: it != end;++it) nuclear@0: { nuclear@0: if ((*it).meshes.empty())continue; nuclear@0: nuclear@0: aiNode* node; nuclear@0: if (pScene->mRootNode->mNumChildren) nuclear@0: { nuclear@0: node = *cc = new aiNode(); nuclear@0: node->mParent = pScene->mRootNode; nuclear@0: } nuclear@0: else node = *cc;++cc; nuclear@0: node->mName.Set((*it).name); nuclear@0: nuclear@0: // add all meshes nuclear@0: node->mNumMeshes = (unsigned int)(*it).meshes.size(); nuclear@0: unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ]; nuclear@0: for (std::vector< MeshInformation >::iterator it2 = (*it).meshes.begin(), nuclear@0: end2 = (*it).meshes.end(); it2 != end2; ++it2) nuclear@0: { nuclear@0: ai_assert(!(*it2).vertices.empty()); nuclear@0: nuclear@0: // allocate the mesh nuclear@0: *pi++ = meshIdx; nuclear@0: aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh(); nuclear@0: mesh->mMaterialIndex = meshIdx++; nuclear@0: nuclear@0: mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; nuclear@0: nuclear@0: // allocate storage for the vertex components and copy them nuclear@0: mesh->mNumVertices = (unsigned int)(*it2).vertices.size(); nuclear@0: mesh->mVertices = new aiVector3D[ mesh->mNumVertices ]; nuclear@0: ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices); nuclear@0: nuclear@0: if ((*it2).colors.size()) nuclear@0: { nuclear@0: ai_assert((*it2).colors.size() == mesh->mNumVertices); nuclear@0: nuclear@0: mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ]; nuclear@0: ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices); nuclear@0: } nuclear@0: nuclear@0: // generate triangles nuclear@0: ai_assert(0 == mesh->mNumVertices % 3); nuclear@0: aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ]; nuclear@0: aiFace* const fcEnd = fc + mesh->mNumFaces; nuclear@0: unsigned int n = 0; nuclear@0: while (fc != fcEnd) nuclear@0: { nuclear@0: aiFace& f = *fc++; nuclear@0: f.mIndices = new unsigned int[f.mNumIndices = 3]; nuclear@0: for (unsigned int m = 0; m < 3;++m) nuclear@0: f.mIndices[m] = n++; nuclear@0: } nuclear@0: nuclear@0: // generate a material for the mesh nuclear@0: aiMaterial* mat = new aiMaterial(); nuclear@0: nuclear@0: aiColor4D clr(1.0f,1.0f,1.0f,1.0f); nuclear@0: if ("%default%" == (*it2).name) // a gray default material nuclear@0: { nuclear@0: clr.r = clr.g = clr.b = 0.6f; nuclear@0: } nuclear@0: else if ((*it2).name.length() > 0) // a texture nuclear@0: { nuclear@0: aiString s; nuclear@0: s.Set((*it2).name); nuclear@0: mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); nuclear@0: } nuclear@0: mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); nuclear@0: *mats++ = mat; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: #endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER