diff options
Diffstat (limited to 'src/3rdparty/assimp/code/UnrealLoader.cpp')
-rw-r--r-- | src/3rdparty/assimp/code/UnrealLoader.cpp | 713 |
1 files changed, 358 insertions, 355 deletions
diff --git a/src/3rdparty/assimp/code/UnrealLoader.cpp b/src/3rdparty/assimp/code/UnrealLoader.cpp index df1796042..ad839fb25 100644 --- a/src/3rdparty/assimp/code/UnrealLoader.cpp +++ b/src/3rdparty/assimp/code/UnrealLoader.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. --------------------------------------------------------------------------- */ @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/ */ -#include "AssimpPCH.h" + #ifndef ASSIMP_BUILD_NO_3D_IMPORTER @@ -56,384 +56,387 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "fast_atof.h" #include "ConvertToLHProcess.h" +#include <assimp/Importer.hpp> +#include <assimp/DefaultLogger.hpp> +#include <assimp/IOSystem.hpp> +#include <assimp/scene.h> + +#include <memory> + using namespace Assimp; static const aiImporterDesc desc = { - "Unreal Mesh Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "3d uc" + "Unreal Mesh Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "3d uc" }; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer UnrealImporter::UnrealImporter() -: configFrameID (0) -, configHandleFlags (true) +: configFrameID (0) +, configHandleFlags (true) {} // ------------------------------------------------------------------------------------------------ -// Destructor, private as well +// Destructor, private as well UnrealImporter::~UnrealImporter() {} // ------------------------------------------------------------------------------------------------ -// 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 UnrealImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const { - return SimpleExtensionCheck(pFile,"3d","uc"); + return SimpleExtensionCheck(pFile,"3d","uc"); } // ------------------------------------------------------------------------------------------------ // Build a string of all file extensions supported const aiImporterDesc* UnrealImporter::GetInfo () const { - return &desc; + return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties for the loader void UnrealImporter::SetupProperties(const Importer* pImp) { - // The - // AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME,-1); - if(static_cast<unsigned int>(-1) == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } - - // AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true - configHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS,1)); + // The + // AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the + // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME,-1); + if(static_cast<unsigned int>(-1) == configFrameID) { + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); + } + + // AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true + configHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS,1)); } // ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void UnrealImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) +// Imports the given file into the given scene structure. +void UnrealImporter::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) { - // For any of the 3 files being passed get the three correct paths - // First of all, determine file extension - std::string::size_type pos = pFile.find_last_of('.'); - std::string extension = GetExtension(pFile); - - std::string d_path,a_path,uc_path; - if (extension == "3d") { - // jjjj_d.3d - // jjjj_a.3d - pos = pFile.find_last_of('_'); - if (std::string::npos == pos) { - throw DeadlyImportError("UNREAL: Unexpected naming scheme"); - } - extension = pFile.substr(0,pos); - } - else { - extension = pFile.substr(0,pos); - } - - // build proper paths - d_path = extension+"_d.3d"; - a_path = extension+"_a.3d"; - uc_path = extension+".uc"; - - DefaultLogger::get()->debug("UNREAL: data file is " + d_path); - DefaultLogger::get()->debug("UNREAL: aniv file is " + a_path); - DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path); - - // and open the files ... we can't live without them - IOStream* p = pIOHandler->Open(d_path); - if (!p) - throw DeadlyImportError("UNREAL: Unable to open _d file"); - StreamReaderLE d_reader(pIOHandler->Open(d_path)); - - const uint16_t numTris = d_reader.GetI2(); - const uint16_t numVert = d_reader.GetI2(); - d_reader.IncPtr(44); - if (!numTris || numVert < 3) - throw DeadlyImportError("UNREAL: Invalid number of vertices/triangles"); - - // maximum texture index - unsigned int maxTexIdx = 0; - - // collect triangles - std::vector<Unreal::Triangle> triangles(numTris); - for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) { - Unreal::Triangle& tri = *it; - - for (unsigned int i = 0; i < 3;++i) { - - tri.mVertex[i] = d_reader.GetI2(); - if (tri.mVertex[i] >= numTris) { - DefaultLogger::get()->warn("UNREAL: vertex index out of range"); - tri.mVertex[i] = 0; - } - } - tri.mType = d_reader.GetI1(); - - // handle mesh flagss? - if (configHandleFlags) - tri.mType = Unreal::MF_NORMAL_OS; - else { - // ignore MOD and MASKED for the moment, treat them as two-sided - if (tri.mType == Unreal::MF_NORMAL_MOD_TS || tri.mType == Unreal::MF_NORMAL_MASKED_TS) - tri.mType = Unreal::MF_NORMAL_TS; - } - d_reader.IncPtr(1); - - for (unsigned int i = 0; i < 3;++i) - for (unsigned int i2 = 0; i2 < 2;++i2) - tri.mTex[i][i2] = d_reader.GetI1(); - - tri.mTextureNum = d_reader.GetI1(); - maxTexIdx = std::max(maxTexIdx,(unsigned int)tri.mTextureNum); - d_reader.IncPtr(1); - } - - p = pIOHandler->Open(a_path); - if (!p) - throw DeadlyImportError("UNREAL: Unable to open _a file"); - StreamReaderLE a_reader(pIOHandler->Open(a_path)); - - // read number of frames - const uint32_t numFrames = a_reader.GetI2(); - if (configFrameID >= numFrames) - throw DeadlyImportError("UNREAL: The requested frame does not exist"); - - uint32_t st = a_reader.GetI2(); - if (st != numVert*4) - throw DeadlyImportError("UNREAL: Unexpected aniv file length"); - - // skip to our frame - a_reader.IncPtr(configFrameID *numVert*4); - - // collect vertices - std::vector<aiVector3D> vertices(numVert); - for (std::vector<aiVector3D>::iterator it = vertices.begin(), end = vertices.end(); it != end; ++it) { - int32_t val = a_reader.GetI4(); - Unreal::DecompressVertex(*it,val); - } - - // list of textures. - std::vector< std::pair<unsigned int, std::string> > textures; - - // allocate the output scene - aiNode* nd = pScene->mRootNode = new aiNode(); - nd->mName.Set("<UnrealRoot>"); - - // we can live without the uc file if necessary - boost::scoped_ptr<IOStream> pb (pIOHandler->Open(uc_path)); - if (pb.get()) { - - std::vector<char> _data; - TextFileToBuffer(pb.get(),_data); - const char* data = &_data[0]; - - std::vector< std::pair< std::string,std::string > > tempTextures; - - // do a quick search in the UC file for some known, usually texture-related, tags - for (;*data;++data) { - if (TokenMatchI(data,"#exec",5)) { - SkipSpacesAndLineEnd(&data); - - // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...] - if (TokenMatchI(data,"TEXTURE",7)) { - SkipSpacesAndLineEnd(&data); - - if (TokenMatchI(data,"IMPORT",6)) { - tempTextures.push_back(std::pair< std::string,std::string >()); - std::pair< std::string,std::string >& me = tempTextures.back(); - for (;!IsLineEnd(*data);++data) { - if (!::ASSIMP_strincmp(data,"NAME=",5)) { - const char *d = data+=5; - for (;!IsSpaceOrNewLine(*data);++data); - me.first = std::string(d,(size_t)(data-d)); - } - else if (!::ASSIMP_strincmp(data,"FILE=",5)) { - const char *d = data+=5; - for (;!IsSpaceOrNewLine(*data);++data); - me.second = std::string(d,(size_t)(data-d)); - } - } - if (!me.first.length() || !me.second.length()) - tempTextures.pop_back(); - } - } - // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1 - // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2 - else if (TokenMatchI(data,"MESHMAP",7)) { - SkipSpacesAndLineEnd(&data); - - if (TokenMatchI(data,"SETTEXTURE",10)) { - - textures.push_back(std::pair<unsigned int, std::string>()); - std::pair<unsigned int, std::string>& me = textures.back(); - - for (;!IsLineEnd(*data);++data) { - if (!::ASSIMP_strincmp(data,"NUM=",4)) { - data += 4; - me.first = strtoul10(data,&data); - } - else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) { - data += 8; - const char *d = data; - for (;!IsSpaceOrNewLine(*data);++data); - me.second = std::string(d,(size_t)(data-d)); - - // try to find matching path names, doesn't care if we don't find them - for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin(); - it != tempTextures.end(); ++it) { - if ((*it).first == me.second) { - me.second = (*it).second; - break; - } - } - } - } - } - else if (TokenMatchI(data,"SCALE",5)) { - - for (;!IsLineEnd(*data);++data) { - if (data[0] == 'X' && data[1] == '=') { - data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.a1); - } - else if (data[0] == 'Y' && data[1] == '=') { - data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.b2); - } - else if (data[0] == 'Z' && data[1] == '=') { - data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.c3); - } - } - } - } - } - } - } - else { - DefaultLogger::get()->error("Unable to open .uc file"); - } - - std::vector<Unreal::TempMat> materials; - materials.reserve(textures.size()*2+5); - - // find out how many output meshes and materials we'll have and build material indices - for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) { - Unreal::Triangle& tri = *it; - Unreal::TempMat mat(tri); - std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat); - if (nt == materials.end()) { - // add material - tri.matIndex = materials.size(); - mat.numFaces = 1; - materials.push_back(mat); - - ++pScene->mNumMeshes; - } - else { - tri.matIndex = static_cast<unsigned int>(nt-materials.begin()); - ++nt->numFaces; - } - } - - if (!pScene->mNumMeshes) { - throw DeadlyImportError("UNREAL: Unable to find valid mesh data"); - } - - // allocate meshes and bind them to the node graph - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes]; - - nd->mNumMeshes = pScene->mNumMeshes; - nd->mMeshes = new unsigned int[nd->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { - aiMesh* m = pScene->mMeshes[i] = new aiMesh(); - m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - const unsigned int num = materials[i].numFaces; - m->mFaces = new aiFace [num]; - m->mVertices = new aiVector3D [num*3]; - m->mTextureCoords[0] = new aiVector3D [num*3]; - - nd->mMeshes[i] = i; - - // create materials, too - aiMaterial* mat = new aiMaterial(); - pScene->mMaterials[i] = mat; - - // all white by default - texture rulez - aiColor3D color(1.f,1.f,1.f); - - aiString s; - ::sprintf(s.data,"mat%i_tx%i_",i,materials[i].tex); - - // set the two-sided flag - if (materials[i].type == Unreal::MF_NORMAL_TS) { - const int twosided = 1; - mat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); - ::strcat(s.data,"ts_"); - } - else ::strcat(s.data,"os_"); - - // make TRANS faces 90% opaque that RemRedundantMaterials won't catch us - if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) { - const float opac = 0.9f; - mat->AddProperty(&opac,1,AI_MATKEY_OPACITY); - ::strcat(s.data,"tran_"); - } - else ::strcat(s.data,"opaq_"); - - // a special name for the weapon attachment point - if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) { - s.length = ::sprintf(s.data,"$WeaponTag$"); - color = aiColor3D(0.f,0.f,0.f); - } - - // set color and name - mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE); - s.length = ::strlen(s.data); - mat->AddProperty(&s,AI_MATKEY_NAME); - - // set texture, if any - const unsigned int tex = materials[i].tex; - for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) { - if ((*it).first == tex) { - s.Set((*it).second); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); - break; - } - } - } - - // fill them. - for (std::vector<Unreal::Triangle>::iterator it = triangles.begin(), end = triangles.end();it != end; ++it) { - Unreal::Triangle& tri = *it; - Unreal::TempMat mat(tri); - std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat); - - aiMesh* mesh = pScene->mMeshes[nt-materials.begin()]; - aiFace& f = mesh->mFaces[mesh->mNumFaces++]; - f.mIndices = new unsigned int[f.mNumIndices = 3]; - - for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) { - f.mIndices[i] = mesh->mNumVertices; - - mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ]; - mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f); - } - } - - // convert to RH - MakeLeftHandedProcess hero; - hero.Execute(pScene); - - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); + // For any of the 3 files being passed get the three correct paths + // First of all, determine file extension + std::string::size_type pos = pFile.find_last_of('.'); + std::string extension = GetExtension(pFile); + + std::string d_path,a_path,uc_path; + if (extension == "3d") { + // jjjj_d.3d + // jjjj_a.3d + pos = pFile.find_last_of('_'); + if (std::string::npos == pos) { + throw DeadlyImportError("UNREAL: Unexpected naming scheme"); + } + extension = pFile.substr(0,pos); + } + else { + extension = pFile.substr(0,pos); + } + + // build proper paths + d_path = extension+"_d.3d"; + a_path = extension+"_a.3d"; + uc_path = extension+".uc"; + + DefaultLogger::get()->debug("UNREAL: data file is " + d_path); + DefaultLogger::get()->debug("UNREAL: aniv file is " + a_path); + DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path); + + // and open the files ... we can't live without them + IOStream* p = pIOHandler->Open(d_path); + if (!p) + throw DeadlyImportError("UNREAL: Unable to open _d file"); + StreamReaderLE d_reader(pIOHandler->Open(d_path)); + + const uint16_t numTris = d_reader.GetI2(); + const uint16_t numVert = d_reader.GetI2(); + d_reader.IncPtr(44); + if (!numTris || numVert < 3) + throw DeadlyImportError("UNREAL: Invalid number of vertices/triangles"); + + // maximum texture index + unsigned int maxTexIdx = 0; + + // collect triangles + std::vector<Unreal::Triangle> triangles(numTris); + for (auto & tri : triangles) { + for (unsigned int i = 0; i < 3;++i) { + + tri.mVertex[i] = d_reader.GetI2(); + if (tri.mVertex[i] >= numTris) { + DefaultLogger::get()->warn("UNREAL: vertex index out of range"); + tri.mVertex[i] = 0; + } + } + tri.mType = d_reader.GetI1(); + + // handle mesh flagss? + if (configHandleFlags) + tri.mType = Unreal::MF_NORMAL_OS; + else { + // ignore MOD and MASKED for the moment, treat them as two-sided + if (tri.mType == Unreal::MF_NORMAL_MOD_TS || tri.mType == Unreal::MF_NORMAL_MASKED_TS) + tri.mType = Unreal::MF_NORMAL_TS; + } + d_reader.IncPtr(1); + + for (unsigned int i = 0; i < 3;++i) + for (unsigned int i2 = 0; i2 < 2;++i2) + tri.mTex[i][i2] = d_reader.GetI1(); + + tri.mTextureNum = d_reader.GetI1(); + maxTexIdx = std::max(maxTexIdx,(unsigned int)tri.mTextureNum); + d_reader.IncPtr(1); + } + + p = pIOHandler->Open(a_path); + if (!p) + throw DeadlyImportError("UNREAL: Unable to open _a file"); + StreamReaderLE a_reader(pIOHandler->Open(a_path)); + + // read number of frames + const uint32_t numFrames = a_reader.GetI2(); + if (configFrameID >= numFrames) + throw DeadlyImportError("UNREAL: The requested frame does not exist"); + + uint32_t st = a_reader.GetI2(); + if (st != numVert*4) + throw DeadlyImportError("UNREAL: Unexpected aniv file length"); + + // skip to our frame + a_reader.IncPtr(configFrameID *numVert*4); + + // collect vertices + std::vector<aiVector3D> vertices(numVert); + for (auto &vertex : vertices) { + int32_t val = a_reader.GetI4(); + Unreal::DecompressVertex(vertex ,val); + } + + // list of textures. + std::vector< std::pair<unsigned int, std::string> > textures; + + // allocate the output scene + aiNode* nd = pScene->mRootNode = new aiNode(); + nd->mName.Set("<UnrealRoot>"); + + // we can live without the uc file if necessary + std::unique_ptr<IOStream> pb (pIOHandler->Open(uc_path)); + if (pb.get()) { + + std::vector<char> _data; + TextFileToBuffer(pb.get(),_data); + const char* data = &_data[0]; + + std::vector< std::pair< std::string,std::string > > tempTextures; + + // do a quick search in the UC file for some known, usually texture-related, tags + for (;*data;++data) { + if (TokenMatchI(data,"#exec",5)) { + SkipSpacesAndLineEnd(&data); + + // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...] + if (TokenMatchI(data,"TEXTURE",7)) { + SkipSpacesAndLineEnd(&data); + + if (TokenMatchI(data,"IMPORT",6)) { + tempTextures.push_back(std::pair< std::string,std::string >()); + std::pair< std::string,std::string >& me = tempTextures.back(); + for (;!IsLineEnd(*data);++data) { + if (!::ASSIMP_strincmp(data,"NAME=",5)) { + const char *d = data+=5; + for (;!IsSpaceOrNewLine(*data);++data); + me.first = std::string(d,(size_t)(data-d)); + } + else if (!::ASSIMP_strincmp(data,"FILE=",5)) { + const char *d = data+=5; + for (;!IsSpaceOrNewLine(*data);++data); + me.second = std::string(d,(size_t)(data-d)); + } + } + if (!me.first.length() || !me.second.length()) + tempTextures.pop_back(); + } + } + // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1 + // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2 + else if (TokenMatchI(data,"MESHMAP",7)) { + SkipSpacesAndLineEnd(&data); + + if (TokenMatchI(data,"SETTEXTURE",10)) { + + textures.push_back(std::pair<unsigned int, std::string>()); + std::pair<unsigned int, std::string>& me = textures.back(); + + for (;!IsLineEnd(*data);++data) { + if (!::ASSIMP_strincmp(data,"NUM=",4)) { + data += 4; + me.first = strtoul10(data,&data); + } + else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) { + data += 8; + const char *d = data; + for (;!IsSpaceOrNewLine(*data);++data); + me.second = std::string(d,(size_t)(data-d)); + + // try to find matching path names, doesn't care if we don't find them + for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin(); + it != tempTextures.end(); ++it) { + if ((*it).first == me.second) { + me.second = (*it).second; + break; + } + } + } + } + } + else if (TokenMatchI(data,"SCALE",5)) { + + for (;!IsLineEnd(*data);++data) { + if (data[0] == 'X' && data[1] == '=') { + data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.a1); + } + else if (data[0] == 'Y' && data[1] == '=') { + data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.b2); + } + else if (data[0] == 'Z' && data[1] == '=') { + data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.c3); + } + } + } + } + } + } + } + else { + DefaultLogger::get()->error("Unable to open .uc file"); + } + + std::vector<Unreal::TempMat> materials; + materials.reserve(textures.size()*2+5); + + // find out how many output meshes and materials we'll have and build material indices + for (Unreal::Triangle &tri : triangles) { + Unreal::TempMat mat(tri); + std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat); + if (nt == materials.end()) { + // add material + tri.matIndex = materials.size(); + mat.numFaces = 1; + materials.push_back(mat); + + ++pScene->mNumMeshes; + } + else { + tri.matIndex = static_cast<unsigned int>(nt-materials.begin()); + ++nt->numFaces; + } + } + + if (!pScene->mNumMeshes) { + throw DeadlyImportError("UNREAL: Unable to find valid mesh data"); + } + + // allocate meshes and bind them to the node graph + pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes]; + + nd->mNumMeshes = pScene->mNumMeshes; + nd->mMeshes = new unsigned int[nd->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { + aiMesh* m = pScene->mMeshes[i] = new aiMesh(); + m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + const unsigned int num = materials[i].numFaces; + m->mFaces = new aiFace [num]; + m->mVertices = new aiVector3D [num*3]; + m->mTextureCoords[0] = new aiVector3D [num*3]; + + nd->mMeshes[i] = i; + + // create materials, too + aiMaterial* mat = new aiMaterial(); + pScene->mMaterials[i] = mat; + + // all white by default - texture rulez + aiColor3D color(1.f,1.f,1.f); + + aiString s; + ::ai_snprintf( s.data, MAXLEN, "mat%u_tx%u_",i,materials[i].tex ); + + // set the two-sided flag + if (materials[i].type == Unreal::MF_NORMAL_TS) { + const int twosided = 1; + mat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); + ::strcat(s.data,"ts_"); + } + else ::strcat(s.data,"os_"); + + // make TRANS faces 90% opaque that RemRedundantMaterials won't catch us + if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) { + const float opac = 0.9f; + mat->AddProperty(&opac,1,AI_MATKEY_OPACITY); + ::strcat(s.data,"tran_"); + } + else ::strcat(s.data,"opaq_"); + + // a special name for the weapon attachment point + if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) { + s.length = ::ai_snprintf( s.data, MAXLEN, "$WeaponTag$" ); + color = aiColor3D(0.f,0.f,0.f); + } + + // set color and name + mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE); + s.length = ::strlen(s.data); + mat->AddProperty(&s,AI_MATKEY_NAME); + + // set texture, if any + const unsigned int tex = materials[i].tex; + for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) { + if ((*it).first == tex) { + s.Set((*it).second); + mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); + break; + } + } + } + + // fill them. + for (const Unreal::Triangle &tri : triangles) { + Unreal::TempMat mat(tri); + std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat); + + aiMesh* mesh = pScene->mMeshes[nt-materials.begin()]; + aiFace& f = mesh->mFaces[mesh->mNumFaces++]; + f.mIndices = new unsigned int[f.mNumIndices = 3]; + + for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) { + f.mIndices[i] = mesh->mNumVertices; + + mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ]; + mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f); + } + } + + // convert to RH + MakeLeftHandedProcess hero; + hero.Execute(pScene); + + FlipWindingOrderProcess flipper; + flipper.Execute(pScene); } #endif // !! ASSIMP_BUILD_NO_3D_IMPORTER |