aboutsummaryrefslogtreecommitdiff
path: root/NvCloth/samples/external/assimp-4.1.0/code/IRRMeshLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NvCloth/samples/external/assimp-4.1.0/code/IRRMeshLoader.cpp')
-rw-r--r--NvCloth/samples/external/assimp-4.1.0/code/IRRMeshLoader.cpp535
1 files changed, 535 insertions, 0 deletions
diff --git a/NvCloth/samples/external/assimp-4.1.0/code/IRRMeshLoader.cpp b/NvCloth/samples/external/assimp-4.1.0/code/IRRMeshLoader.cpp
new file mode 100644
index 0000000..a63a2a1
--- /dev/null
+++ b/NvCloth/samples/external/assimp-4.1.0/code/IRRMeshLoader.cpp
@@ -0,0 +1,535 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, 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
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ 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
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+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
+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
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the IrrMesh importer class */
+
+
+
+#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
+
+#include "IRRMeshLoader.h"
+#include "ParsingUtils.h"
+#include "fast_atof.h"
+#include <memory>
+#include <assimp/IOSystem.hpp>
+#include <assimp/mesh.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+#include <assimp/importerdesc.h>
+#include "Macros.h"
+
+using namespace Assimp;
+using namespace irr;
+using namespace irr::io;
+
+static const aiImporterDesc desc = {
+ "Irrlicht Mesh Reader",
+ "",
+ "",
+ "http://irrlicht.sourceforge.net/",
+ aiImporterFlags_SupportTextFlavour,
+ 0,
+ 0,
+ 0,
+ 0,
+ "xml irrmesh"
+};
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+IRRMeshImporter::IRRMeshImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well
+IRRMeshImporter::~IRRMeshImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file.
+bool IRRMeshImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+{
+ /* NOTE: A simple check for the file extension is not enough
+ * here. Irrmesh and irr are easy, but xml is too generic
+ * and could be collada, too. So we need to open the file and
+ * search for typical tokens.
+ */
+ const std::string extension = GetExtension(pFile);
+
+ if (extension == "irrmesh")return true;
+ else if (extension == "xml" || checkSig)
+ {
+ /* If CanRead() is called to check whether the loader
+ * supports a specific file extension in general we
+ * must return true here.
+ */
+ if (!pIOHandler)return true;
+ const char* tokens[] = {"irrmesh"};
+ return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+ }
+ return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a list of all file extensions which are handled by this class
+const aiImporterDesc* IRRMeshImporter::GetInfo () const
+{
+ return &desc;
+}
+
+static void releaseMaterial( aiMaterial **mat ) {
+ if(*mat!= nullptr) {
+ delete *mat;
+ *mat = nullptr;
+ }
+}
+
+static void releaseMesh( aiMesh **mesh ) {
+ if (*mesh != nullptr){
+ delete *mesh;
+ *mesh = nullptr;
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void IRRMeshImporter::InternReadFile( const std::string& pFile,
+ aiScene* pScene, IOSystem* pIOHandler)
+{
+ std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+ // Check whether we can read from the file
+ if( file.get() == NULL)
+ throw DeadlyImportError( "Failed to open IRRMESH file " + pFile + "");
+
+ // Construct the irrXML parser
+ CIrrXML_IOStreamReader st(file.get());
+ reader = createIrrXMLReader((IFileReadCallBack*) &st);
+
+ // final data
+ std::vector<aiMaterial*> materials;
+ std::vector<aiMesh*> meshes;
+ materials.reserve (5);
+ meshes.reserve(5);
+
+ // temporary data - current mesh buffer
+ aiMaterial* curMat = nullptr;
+ aiMesh* curMesh = nullptr;
+ unsigned int curMatFlags = 0;
+
+ std::vector<aiVector3D> curVertices,curNormals,curTangents,curBitangents;
+ std::vector<aiColor4D> curColors;
+ std::vector<aiVector3D> curUVs,curUV2s;
+
+ // some temporary variables
+ int textMeaning = 0;
+ int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents
+ bool useColors = false;
+
+ // Parse the XML file
+ while (reader->read()) {
+ switch (reader->getNodeType()) {
+ case EXN_ELEMENT:
+
+ if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
+ // end of previous buffer. A material and a mesh should be there
+ if ( !curMat || !curMesh) {
+ DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
+ releaseMaterial( &curMat );
+ releaseMesh( &curMesh );
+ } else {
+ materials.push_back(curMat);
+ meshes.push_back(curMesh);
+ }
+ curMat = nullptr;
+ curMesh = nullptr;
+
+ curVertices.clear();
+ curColors.clear();
+ curNormals.clear();
+ curUV2s.clear();
+ curUVs.clear();
+ curTangents.clear();
+ curBitangents.clear();
+ }
+
+
+ if (!ASSIMP_stricmp(reader->getNodeName(),"material")) {
+ if (curMat) {
+ DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
+ releaseMaterial( &curMat );
+ }
+ curMat = ParseMaterial(curMatFlags);
+ }
+ /* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices"))
+ {
+ int num = reader->getAttributeValueAsInt("vertexCount");
+
+ if (!num) {
+ // This is possible ... remove the mesh from the list and skip further reading
+ DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
+
+ releaseMaterial( &curMat );
+ releaseMesh( &curMesh );
+ textMeaning = 0;
+ continue;
+ }
+
+ curVertices.reserve(num);
+ curNormals.reserve(num);
+ curColors.reserve(num);
+ curUVs.reserve(num);
+
+ // Determine the file format
+ const char* t = reader->getAttributeValueSafe("type");
+ if (!ASSIMP_stricmp("2tcoords", t)) {
+ curUV2s.reserve (num);
+ vertexFormat = 1;
+
+ if (curMatFlags & AI_IRRMESH_EXTRA_2ND_TEXTURE) {
+ // *********************************************************
+ // We have a second texture! So use this UV channel
+ // for it. The 2nd texture can be either a normal
+ // texture (solid_2layer or lightmap_xxx) or a normal
+ // map (normal_..., parallax_...)
+ // *********************************************************
+ int idx = 1;
+ aiMaterial* mat = ( aiMaterial* ) curMat;
+
+ if (curMatFlags & AI_IRRMESH_MAT_lightmap){
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_LIGHTMAP(0));
+ }
+ else if (curMatFlags & AI_IRRMESH_MAT_normalmap_solid){
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0));
+ }
+ else if (curMatFlags & AI_IRRMESH_MAT_solid_2layer) {
+ mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
+ }
+ }
+ }
+ else if (!ASSIMP_stricmp("tangents", t)) {
+ curTangents.reserve (num);
+ curBitangents.reserve (num);
+ vertexFormat = 2;
+ }
+ else if (ASSIMP_stricmp("standard", t)) {
+ releaseMaterial( &curMat );
+ DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
+ }
+ else vertexFormat = 0;
+ textMeaning = 1;
+ }
+ else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) {
+ if (curVertices.empty() && curMat) {
+ releaseMaterial( &curMat );
+ throw DeadlyImportError("IRRMESH: indices must come after vertices");
+ }
+
+ textMeaning = 2;
+
+ // start a new mesh
+ curMesh = new aiMesh();
+
+ // allocate storage for all faces
+ curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
+ if (!curMesh->mNumVertices) {
+ // This is possible ... remove the mesh from the list and skip further reading
+ DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
+
+ // mesh - away
+ releaseMesh( &curMesh );
+
+ // material - away
+ releaseMaterial( &curMat );
+
+ textMeaning = 0;
+ continue;
+ }
+
+ if (curMesh->mNumVertices % 3) {
+ DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
+ }
+
+ curMesh->mNumFaces = curMesh->mNumVertices / 3;
+ curMesh->mFaces = new aiFace[curMesh->mNumFaces];
+
+ // setup some members
+ curMesh->mMaterialIndex = (unsigned int)materials.size();
+ curMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+ // allocate storage for all vertices
+ curMesh->mVertices = new aiVector3D[curMesh->mNumVertices];
+
+ if (curNormals.size() == curVertices.size()) {
+ curMesh->mNormals = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curTangents.size() == curVertices.size()) {
+ curMesh->mTangents = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curBitangents.size() == curVertices.size()) {
+ curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curColors.size() == curVertices.size() && useColors) {
+ curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices];
+ }
+ if (curUVs.size() == curVertices.size()) {
+ curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices];
+ }
+ if (curUV2s.size() == curVertices.size()) {
+ curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices];
+ }
+ }
+ break;
+
+ case EXN_TEXT:
+ {
+ const char* sz = reader->getNodeData();
+ if (textMeaning == 1) {
+ textMeaning = 0;
+
+ // read vertices
+ do {
+ SkipSpacesAndLineEnd(&sz);
+ aiVector3D temp;aiColor4D c;
+
+ // Read the vertex position
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+ curVertices.push_back(temp);
+
+ // Read the vertex normals
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+ curNormals.push_back(temp);
+
+ // read the vertex colors
+ uint32_t clr = strtoul16(sz,&sz);
+ ColorFromARGBPacked(clr,c);
+
+ if (!curColors.empty() && c != *(curColors.end()-1))
+ useColors = true;
+
+ curColors.push_back(c);
+ SkipSpaces(&sz);
+
+
+ // read the first UV coordinate set
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+ temp.z = 0.f;
+ temp.y = 1.f - temp.y; // DX to OGL
+ curUVs.push_back(temp);
+
+ // read the (optional) second UV coordinate set
+ if (vertexFormat == 1) {
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ temp.y = 1.f - temp.y; // DX to OGL
+ curUV2s.push_back(temp);
+ }
+ // read optional tangent and bitangent vectors
+ else if (vertexFormat == 2) {
+ // tangents
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+ temp.y *= -1.0f;
+ curTangents.push_back(temp);
+
+ // bitangents
+ sz = fast_atoreal_move<float>(sz,(float&)temp.x);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.z);
+ SkipSpaces(&sz);
+
+ sz = fast_atoreal_move<float>(sz,(float&)temp.y);
+ SkipSpaces(&sz);
+ temp.y *= -1.0f;
+ curBitangents.push_back(temp);
+ }
+ }
+
+ /* IMPORTANT: We assume that each vertex is specified in one
+ line. So we can skip the rest of the line - unknown vertex
+ elements are ignored.
+ */
+
+ while (SkipLine(&sz));
+ }
+ else if (textMeaning == 2) {
+ textMeaning = 0;
+
+ // read indices
+ aiFace* curFace = curMesh->mFaces;
+ aiFace* const faceEnd = curMesh->mFaces + curMesh->mNumFaces;
+
+ aiVector3D* pcV = curMesh->mVertices;
+ aiVector3D* pcN = curMesh->mNormals;
+ aiVector3D* pcT = curMesh->mTangents;
+ aiVector3D* pcB = curMesh->mBitangents;
+ aiColor4D* pcC0 = curMesh->mColors[0];
+ aiVector3D* pcT0 = curMesh->mTextureCoords[0];
+ aiVector3D* pcT1 = curMesh->mTextureCoords[1];
+
+ unsigned int curIdx = 0;
+ unsigned int total = 0;
+ while(SkipSpacesAndLineEnd(&sz)) {
+ if (curFace >= faceEnd) {
+ DefaultLogger::get()->error("IRRMESH: Too many indices");
+ break;
+ }
+ if (!curIdx) {
+ curFace->mNumIndices = 3;
+ curFace->mIndices = new unsigned int[3];
+ }
+
+ unsigned int idx = strtoul10(sz,&sz);
+ if (idx >= curVertices.size()) {
+ DefaultLogger::get()->error("IRRMESH: Index out of range");
+ idx = 0;
+ }
+
+ curFace->mIndices[curIdx] = total++;
+
+ *pcV++ = curVertices[idx];
+ if (pcN)*pcN++ = curNormals[idx];
+ if (pcT)*pcT++ = curTangents[idx];
+ if (pcB)*pcB++ = curBitangents[idx];
+ if (pcC0)*pcC0++ = curColors[idx];
+ if (pcT0)*pcT0++ = curUVs[idx];
+ if (pcT1)*pcT1++ = curUV2s[idx];
+
+ if (++curIdx == 3) {
+ ++curFace;
+ curIdx = 0;
+ }
+ }
+
+ if (curFace != faceEnd)
+ DefaultLogger::get()->error("IRRMESH: Not enough indices");
+
+ // Finish processing the mesh - do some small material workarounds
+ if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) {
+ // Take the opacity value of the current material
+ // from the common vertex color alpha
+ aiMaterial* mat = (aiMaterial*)curMat;
+ mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY);
+ }
+ }}
+ break;
+
+ default:
+ // GCC complains here ...
+ break;
+
+ };
+ }
+
+ // End of the last buffer. A material and a mesh should be there
+ if (curMat || curMesh) {
+ if ( !curMat || !curMesh) {
+ DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
+ releaseMaterial( &curMat );
+ releaseMesh( &curMesh );
+ }
+ else {
+ materials.push_back(curMat);
+ meshes.push_back(curMesh);
+ }
+ }
+
+ if (materials.empty())
+ throw DeadlyImportError("IRRMESH: Unable to read a mesh from this file");
+
+
+ // now generate the output scene
+ pScene->mNumMeshes = (unsigned int)meshes.size();
+ pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+ for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
+ pScene->mMeshes[i] = meshes[i];
+
+ // clean this value ...
+ pScene->mMeshes[i]->mNumUVComponents[3] = 0;
+ }
+
+ pScene->mNumMaterials = (unsigned int)materials.size();
+ pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+ ::memcpy(pScene->mMaterials,&materials[0],sizeof(void*)*pScene->mNumMaterials);
+
+ pScene->mRootNode = new aiNode();
+ pScene->mRootNode->mName.Set("<IRRMesh>");
+ 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;
+
+ // clean up and return
+ delete reader;
+ AI_DEBUG_INVALIDATE_PTR(reader);
+}
+
+#endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER